UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)

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

思路:首先,图中得有环的存在才有解,其次再解决这个最小平均权值为多少。一般这种就是二分猜平均权值了,因为环在哪也难以找出来,还有可能是一条边属于多个环。对于每个猜到的平均值,如果对应环的存在,那么这个环的每条边的权减去这个平均值之后,用spfa算法就能判断其是否有环的存在即可。

  假设环上各边权值为:w1+w2+...+wk。

  式子:w1+w2+...+wk<k*even   相当于   (w1-even)+(w2-even)+...(wk-even)< 0。即更新完边权后应i该是有环存在的。

  对于猜测的平均权值mid,如果不能找到环,则说明mid应该更大。

 1 #include <bits/stdc++.h>
 2 #define LL long long
 3 #define pii pair<int,int>
 4 #define INF 0x7f7f7f7f
 5 using namespace std;
 6 const int N=60606;
 7 vector<int> vect[N];
 8 struct node
 9 {
10     int from,to;
11     double cost;
12     node(){};
13     node(int from,int to,int cost):from(from),to(to),cost(cost){};
14 }edge[N];
15 int edge_cnt;
16 int big, small;
17 void add_node(int from,int to,double cost)
18 {
19     edge[edge_cnt]=node(from, to, cost);
20     vect[from].push_back(edge_cnt++);
21 }
22
23 int inq[N], cnt[N];
24 double dist[N];
25 bool spfa(int n, double q)
26 {
27     memset(inq,0,sizeof(inq));
28     memset(cnt,0,sizeof(cnt));
29     deque<int> que;
30     for(int i=1; i<=n; i++)    dist[i]=0.0, inq[i]=1, que.push_back(i); //因为是判断负环的,所以dist初始化为0即可。
31     while(!que.empty())
32     {
33         int x=que.front();que.pop_front();
34         inq[x]=0;
35         for(int i=0; i<vect[x].size(); i++)
36         {
37             node e=edge[vect[x][i]];
38             if(dist[e.to]>dist[x]+e.cost-q  )
39             {
40                 dist[e.to]=dist[x]+e.cost-q ;
41                 if(!inq[e.to])
42                 {
43                     inq[e.to]=1;
44                     que.push_back(e.to);
45                     if(++cnt[e.to]>n)
46                         return true;
47                 }
48             }
49         }
50     }
51     return false;
52 }
53
54 double cal(int n)
55 {
56     double l=small, r=big, ans=0.0;
57     while(r-l>1e-3)
58     {
59         double mid=(l+r)/2;
60         if( spfa(n, mid) )  r=mid;    //有负环
61         else               l=mid;
62     }
63     return l;
64 }
65
66 int main()
67 {
68    // freopen("input.txt", "r", stdin);
69     int n, m, t, a, b, c, j=0;
70     cin>>t;
71     while(t--)
72     {
73         scanf("%d%d",&n,&m);
74         edge_cnt=0;
75         for(int i=0; i<=n; i++)    vect[i].clear();
76         memset(edge,0,sizeof(edge));
77         big=0;
78         small=INF;
79
80         for(int i=0; i<m; i++)
81         {
82             scanf("%d%d%d",&a,&b,&c);
83             add_node(a,b,c);
84             small=min(small,c);
85             big=max(big, c);
86         }
87         if( !spfa(n, big+1) ) printf("Case #%d: No cycle found.\n", ++j);
88         else    printf("Case #%d: %.2f\n", ++j, cal(n));
89     }
90     return 0;
91 }

AC代码

时间: 2024-08-28 10:02:08

UVA 11090 Going in Cycle!! 环平均权值(bellman-ford,spfa,二分)的相关文章

UVA - 11090 Going in Cycle!! (Bellman-Ford算法判负环)

Description I I U P C 2 0 06 Problem G: Going in Cycle!! Input: standard input Output: standard output You are given a weighted directed graph with n vertices and m edges. Each cycle in the graph has a weight, which equals to sum of its edges. There

UVA 11090 - Going in Cycle!!(Bellman-Ford)

UVA 11090 - Going in Cycle!! 题目链接 题意:给定一个有向图,球平均权值最小的回路 思路:二分+判负环,每次二分一个值mid,判断是否存在小于mid的环,那么就是(w1 + w2 + w3...) / n < mid == w1 - mid + w2 - mid + w3 - mid .... < 0,所以每次二分的时候,把边权值减掉mid,之后bellmanford判负环即可 代码: #include <cstdio> #include <cst

UVA 11090 - Going in Cycle!!

二分+SPFA找负环 11090 - Going in Cycle!! Time limit: 3.000 seconds I I U P C 2 0 0 6 Problem G: Going in Cycle!! Input: standard input Output: standard output You are given a weighted directed graph with n vertices and m edges. Each cycle in the graph has

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可以解决

UVA 11090 Going in Cycle!!(Bellman-Ford判断负圈)

题意:给定一个n个点m条边的加权有向图,求平均权值最小的回路. 思路:使用二分法求解,对于每一个枚举值mid,判断每条边权值减去mid后有无负圈即可. #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<

UVa 11090 Going in Cycle!! (Bellman_Ford)

题意:给定一个加权有向图,求平均权值最小的回路. 析:先十分答案,假设答案是 ans,那么有这么一个回路,w1+w2+w3+...+wk < k*ans,这样就是答案太大,然后移项可得,(w1-ans)+(w2-ans)+(w3-ans) + ..+(wk-ans) < 0,这样的话就判断是不是有负图就好了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio&g

HDU 3488--Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 &amp;&amp; 经典】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2308    Accepted Submission(s): 1156 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

HDU 1853--Cyclic Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 】

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1950    Accepted Submission(s): 984 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

layout: post title: 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - BellmanFord - 图论 - 训练指南 Going in Cycle!! UVA - 11090 题意 就最小的环的平均权值 题解 分枚举平均值mid,只需判断是否存在平均值小于mid的回路,即判断是否有sum(wi)&