UVA11090 Going in Cycle!!(二分判负环)

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.
"); 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
",l);
67     }return 0;
68 }
View Code
原文地址:https://www.cnblogs.com/kafuuchino/p/9836993.html