码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 11090 Going in Cycle!!【Bellman_Ford】

时间:2015-04-11 14:30:56      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

题意:给出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

 

UVa 11090 Going in Cycle!!【Bellman_Ford】

标签:

原文地址:http://www.cnblogs.com/wuyuewoniu/p/4417576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!