UVA11090 Going in Cycle!!(二分判负环)
二分答案,用spfa判负环。
注意格式;图不一定连通。
复杂度$O(nmlog(maxw-minw))$
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<cmath> 6 #define re register 7 using namespace std; 8 typedef double db; 9 const db eps=1e-7; 10 #define N 100 11 #define M 20000 12 int n,m,t,ri[N]; db d[N],val[M<<1]; bool inh[N],vis[N]; 13 int cnt,hd[M],nxt[M<<1],ed[M],poi[M]; 14 void adde(int x,int y,db v){ 15 nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt; 16 ed[x]=cnt; poi[cnt]=y; val[cnt]=v; 17 } 18 bool spfa(int st,db lim){ 19 memset(d,127,sizeof(d)); 20 memset(inh,0,sizeof(inh)); 21 memset(ri,0,sizeof(ri)); 22 queue<int> h; h.push(st); 23 inh[st]=1; d[st]=0; vis[st]=1; 24 while(!h.empty()){ 25 int x=h.front(); h.pop(); 26 inh[x]=0; 27 for(int i=hd[x];i;i=nxt[i]){ 28 int to=poi[i]; 29 if(d[x]+val[i]-lim<d[to]){ 30 d[to]=d[x]+val[i]-lim; 31 ri[to]=ri[x]+1; vis[to]=1; 32 if(ri[to]>=n) return 1;//出现次数>=n则有环 33 if(!inh[to]) 34 inh[to]=1,h.push(to); 35 } 36 } 37 }return 0; 38 } 39 bool check(db lim){ 40 memset(vis,0,sizeof(vis)); 41 bool ok=0; 42 for(re int i=1;i<=n&&!ok;++i) 43 if(!vis[i]) ok|=spfa(i,lim); 44 return ok; 45 } 46 int main(){ 47 scanf("%d",&t); int q1,q2;db q3; 48 for(int w=1;w<=t;++w){ 49 memset(hd,0,sizeof(hd)); cnt=0; 50 memset(nxt,0,sizeof(nxt)); 51 memset(ed,0,sizeof(ed)); 52 scanf("%d%d",&n,&m); 53 db l=1e8,r=-1e8; 54 for(re int i=1;i<=m;++i){ 55 scanf("%d%d%lf",&q1,&q2,&q3); 56 adde(q1,q2,q3); 57 l=min(q3,l); 58 r=max(q3,r); 59 }printf("Case #%d: ",w); 60 if(!check(r+1))//如果减去最大边+1仍无负环,这个图就是无环图 61 {printf("No cycle found.\n"); continue;} 62 while(fabs(r-l)>eps){//二分 63 db mid=(l+r)/2.0; 64 if(check(mid)) r=mid; 65 else l=mid; 66 }printf("%.2lf\n",l); 67 }return 0; 68 }