在加权有向图中求平均权值最小的回路。
一上手没有思路,看到“回路”,第一想法就是找连通分量,可又是加权图,没什么好思路,那就转换题意:由求回路权值->判负环,求最小值->常用二分答案。
二份答案,再利用利用bellman-ford判负环。
注意:
1、double:经常为了确定每个变量的类型,漏掉了某个变量,调半天心都凉了。干脆全变double。
2、没有告诉m的数据范围,要是在比赛中肯定有人问,要是reply是“read carefully”,总不能猜吧,乖乖用vector吧= =
3、原图为有向图,但不一定强连通,所以所有点要先入队才能找到全部的连通分量(就wa在这里)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<algorithm> 5 #define clr(a,m) memset(a,m,sizeof(a)) 6 #define rep(i,a,b) for(int i=a;i<=b;i++) 7 using namespace std; 8 9 const int MAXN=55; 10 const int INF =1e8; 11 const double eps=1e-3; 12 13 struct Edge{ 14 int u,v; 15 double c; 16 }; 17 18 int inq[MAXN],cnt[MAXN]; 19 double d[MAXN]; 20 vector<Edge>edge; 21 vector<int>G[MAXN]; 22 23 void init(int n) 24 { 25 edge.clear(); 26 rep(i,1,n) 27 G[i].clear(); 28 } 29 30 void add(int u,int v,double c) 31 { 32 edge.push_back((Edge){u,v,c}); 33 int m=edge.size(); 34 G[u].push_back(m-1); 35 } 36 37 double build(int m) 38 { 39 int u,v; 40 double c; 41 double up=0; 42 rep(i,1,m){ 43 scanf("%d%d%lf",&u,&v,&c); 44 up=max(up,c); 45 add(u,v,c); 46 } 47 return up; 48 } 49 50 bool BF(int st,int n) 51 { 52 clr(inq,0); 53 clr(cnt,0); 54 queue<int>q; 55 rep(i,1,n){ 56 if(i==st)d[i]=0; 57 else d[i]=INF; 58 q.push(i); 59 } 60 while(!q.empty()) 61 { 62 int u=q.front();q.pop(); 63 inq[u]=false; 64 int sz=G[u].size(); 65 rep(i,0,sz-1){ 66 Edge e=edge[G[u][i]]; 67 if(d[e.v]>d[u]+e.c){ 68 d[e.v]=d[u]+e.c; 69 if(!inq[e.v]){ 70 q.push(e.v); 71 inq[e.v]=true; 72 if(++cnt[e.v]>n) 73 return true; 74 } 75 } 76 } 77 } 78 return false; 79 } 80 81 bool test(int n,int m,double x) 82 { 83 rep(i,0,m-1) 84 edge[i].c-=x; 85 bool flog=BF(1,n); 86 rep(i,0,m-1) 87 edge[i].c+=x; 88 return flog; 89 } 90 91 int main() 92 { 93 int T,n,m; 94 scanf("%d",&T); 95 for(int ans=1;ans<=T;ans++) 96 { 97 scanf("%d%d",&n,&m); 98 init(n); 99 double up=build(m); 100 101 printf("Case #%d: ",ans); 102 if(!test(n,m,up+1)) 103 printf("No cycle found. "); 104 else{ 105 double l=0,r=up; 106 while(r-l>eps) 107 { 108 double x=l+(r-l)/2; 109 if(test(n,m,x)) 110 r=x; 111 else 112 l=x; 113 } 114 printf("%.2f ",l); 115 } 116 } 117 return 0; 118 }