UVa 11090 Going in Cycle!!【Bellman_Ford】

题意:给出n个点m条边的加权有向图,求平均值最小的回路

自己想的是用DFS找环(真是too young),在比较找到各个环的平均权值,可是代码实现不了,觉得又不太对

后来看书= =好巧妙的办法, 使用二分法求解,首先记录下来这m条边的最大权值ub

然后可以猜测一个mid,只需要判断是否存在平均值小于mid的回路 假设存在一个包含k条边的回路,回路上各条边的权值分别为w1,w,2,w3,----,wk

那么

w1+w2+w3+----+wk<k*mid

又因为联想到Bellman_Ford可以解决负环,把上式转化一下

(w1-mid)+(w2-mid)+(w3-mid)+----(wk-mid)<0

这样先将每条边w(a,b)转化成为w(a,b)-mid,再判断“新”的图中是否存在负环

 

自己看的时候有两个不明白的,就是最开始判断的时候为什么要用ub+1,

是因为ub+1是最差的答案了,它能够尽可能的使得每条边负得最多,如果在这种情况下都找不到负环,那么一定不存在负环

然后就是如果在ub+1的条件下能够找到负环,那么就二分查找一步步找出平均值最小的环,直到到达循环退出的精度

 

代码学习的标程= =

  1 #include<iostream>  

  2 #include<cstdio>  

  3 #include<cstring> 

  4 #include <cmath> 

  5 #include<stack>

  6 #include<vector>

  7 #include<map> 

  8 #include<set>

  9 #include<queue> 

 10 #include<algorithm>  

 11 #define mod=1e9+7;



 12 using namespace std;

 13 

 14 typedef long long LL;

 15 const int INF = 0x7fffffff;

 16 const int maxn=10005;

 17 

 18 struct Edge{

 19     int from,to;



 20     double dist;

 21 };

 22 

 23 struct BellmanFord{

 24     int n,m;

 25     vector<Edge> edges;

 26     vector<int> G[maxn];

 27     bool inq[maxn];

 28     double d[maxn];

 29     int p[maxn];

 30     int cnt[maxn];

 31     

 32     void init(int n){

 33         this->n=n;

 34         for(int i=0;i<n;i++) G[i].clear();

 35         edges.clear();

 36     }

 37     

 38     void AddEdges(int from,int to,double dist){

 39         edges.push_back((Edge){from,to,dist});

 40         m=edges.size();

 41         G[from].push_back(m-1);

 42     }

 43     

 44     bool negativeCycle(){

 45         queue<int> Q;

 46         memset(inq,0,sizeof(inq));

 47         memset(cnt,0,sizeof(cnt));

 48         for(int i=0;i<n;i++) {d[i]=0;inq[0]=true;Q.push(i);}

 49         

 50         while(!Q.empty()){

 51             int u=Q.front();Q.pop();

 52             inq[u]=false;

 53             for(int i=0;i<G[u].size();i++){

 54                 Edge& e=edges[G[u][i]];

 55                 if(d[e.to]>d[u]+e.dist){

 56                     d[e.to]=d[u]+e.dist;

 57                     p[e.to]=G[u][i];

 58                     if(!inq[e.to]){

 59                         Q.push(e.to);

 60                         inq[e.to]=true;

 61                         if(++cnt[e.to]>n) 

 62                         return true;

 63                     }

 64                 }

 65             }

 66         }

 67         return false;

 68     }

 69 };

 70 

 71 BellmanFord solver;

 72 

 73 bool test(double x){

 74     for(int i=0;i<solver.m;i++)

 75     solver.edges[i].dist-=x;

 76     

 77     bool ret=solver.negativeCycle();

 78     for(int i=0;i<solver.m;i++)

 79     solver.edges[i].dist+=x;

 80     return ret;

 81 }

 82 

 83 int main(){

 84     int T;

 85     scanf("%d",&T);

 86     for(int kase=1;kase<=T;kase++){

 87         int n,m;

 88         scanf("%d %d",&n,&m);

 89         solver.init(n);

 90         int ub=0;

 91         while(m--){

 92             int u,v,w;

 93             scanf("%d %d %d",&u,&v,&w);u--;v--;ub=max(ub,w);

 94             solver.AddEdges(u,v,w);            

 95         }

 96         printf("Case #%d: ",kase);

 97         if(!test(ub+1)) printf("No cycle found.\n");

 98         else{

 99             double L=0,R=ub;

100             while(R-L>1e-3){

101                 double M=L+(R-L)/2;

102                 if(test(M)) R=M;else L=M;

103             }

104             printf("%.2lf\n",L);

105         }

106     }

107     return 0;

108 }
View Code

 

你可能感兴趣的:(for)