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 }

 

你可能感兴趣的:(for)