bellman_ford寻找平均权值最小的回路

给定一个有向图,如果存在平均值最小的回路,输出平均值。

使用二分法求解,对于一个猜测值mid,判断是否存在平均值小于mid的回路

如果存在平均值小于mid的包含k条边的回路,那么有w1+w2+w3+...+wk < k * mid,即(w1-mid)+(w2-mid)+..(wk-mid)<0,

即判断是否存在负权回路即可。

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2031&mosmsg=Submission+received+with+ID+14572787

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N = 50+10;
 4 const int INF = 1<<30;
 5 struct Edge
 6 {
 7     int u,v;
 8     double weight;
 9 }g[4000000];
10 double dist[N];
11 void relax(int u, int v,double weight)
12 {
13     if(dist[v] > dist[u] + weight)
14         dist[v] = dist[u] + weight;
15 }
16 bool bellman_ford(int n, int m)
17 {
18     int i,j;
19     for(i=0; i<n-1; ++i)//n-1循环
20         for(j=0; j<m; ++j)//枚举所有的边去松弛最短路径
21         {
22             relax(g[j].u,g[j].v,g[j].weight);
23         }
24     bool flag = false;
25     for(i=0; i<m; ++i)
26         if(dist[g[i].v] > dist[g[i].u] + g[i].weight)
27         {
28             flag = true;
29             break;
30         }
31     return flag;
32 }
33 bool test(double x,int n, int m)
34 {
35     int i;
36     for(i=0; i<m; ++i)
37         g[i].weight -= x;
38     bool ret =  bellman_ford(n,m);
39     for(i=0; i<m; ++i)
40         g[i].weight += x;
41     return ret;
42 }
43 int main()
44 {
45     int n,m,i,t,tCase=1;
46     double l,r;
47     scanf("%d",&t);
48     while(t--)
49     {
50         scanf("%d%d",&n,&m);
51         for(i=1; i<=n; ++i)
52             dist[i] = INF;
53         l = r = 0;
54         for(i=0; i<m; ++i)
55         {
56             scanf("%d%d%lf",&g[i].u,&g[i].v,&g[i].weight);
57             r = r > g[i].weight ? r : g[i].weight;
58         }
59         if(!test(r+1,n,m))printf("Case #%d: No cycle found.\n",tCase++);
60         else
61         {
62             double mid;
63         
64             while(r-l>0.001)//因为题目要求保留2位小数,所以当r-l>0.001时,l就是答案。
65             {
66                 double mid = (r + l ) / 2;
67                 if(test(mid,n,m))
68                     r = mid;
69                 else
70                     l = mid;
71             }
72             printf("Case #%d: %.2lf\n",tCase++,l);
73         }
74         
75     }
76     return 0;
77 }

 

posted @ 2014-11-23 15:40  justPassBy  阅读(383)  评论(0编辑  收藏  举报