UVA 11090 Going in Cycle!!(二分答案+判负环)

在加权有向图中求平均权值最小的回路。

一上手没有思路,看到“回路”,第一想法就是找连通分量,可又是加权图,没什么好思路,那就转换题意:由求回路权值->判负环,求最小值->常用二分答案。

二份答案,再利用利用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.\n");
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\n",l);
115         }
116     }
117     return 0;
118 }
View Code

 

posted @ 2013-08-18 13:17  Thousand Sunny  阅读(276)  评论(0编辑  收藏  举报