T1 最小圈 bzoj 1486
题目大意:
一个环的权值平均值为定义为一个这个环上所有边的权值和除以边数
求最小的环的权值平均值
思路:
二分一个值 把所有边减去这个值
判断是否有负环
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 1061109567 10 #define ll long long 11 #define MAXN 6010 12 #define eps 1e-9 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,m,vis[MAXN],fa[MAXN],q[MAXN],f; 22 double l,r,mid,ans,dis[MAXN],val[MAXN<<1],v[MAXN<<1]; 23 int to[MAXN<<1],nxt[MAXN<<1],fst[MAXN],cnt; 24 void add(int u,int v,double w) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;} 25 void spfa(int x) 26 { 27 vis[x]=1; 28 for(int i=fst[x];i;i=nxt[i]) 29 if(dis[x]+v[i]<dis[to[i]]) 30 if(vis[to[i]]){f=1;return;} 31 else {dis[to[i]]=v[i]+dis[x];spfa(to[i]);} 32 vis[x]=0; 33 } 34 int check(double x) 35 { 36 for(int i=1;i<=cnt;i++) v[i]=val[i]-x; 37 for(int i=1;i<=n;i++) dis[i]=0.0; 38 memset(vis,0,sizeof(vis));f=0; 39 for(int i=1;i<=n;i++) 40 {spfa(i);if(f) return 1;} 41 return 0; 42 } 43 int main() 44 { 45 n=read(),m=read();int a,b;double c; 46 while(m--) {a=read(),b=read();scanf("%lf",&c);add(a,b,c);} 47 l=-1e7,r=1e7; 48 while(r-l>=eps) 49 { 50 mid=(l+r)/2.0; 51 if(check(mid)) ans=mid,r=mid-eps; 52 else l=mid+eps; 53 } 54 printf("%.8lf",ans); 55 }