http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2031
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 a weight, which equals to sum of its edges. There are so many cycles in the graph with different weights. In this problem we want to find a cycle with the minimum mean.
| |
Input | |
The first line of input gives the number of cases, N. N test cases follow. Each one starts with two numbers n and m. m lines follow, each has three positive number a, b, c which means there is an edge from vertex a to b with weight of c.
| |
Output | |
For each test case output one line containing “Case #x: ” followed by a number that is the lowest mean cycle in graph with 2 digits after decimal place, if there is a cycle. Otherwise print “No cycle found.”.
| |
Constraints | |
- n ≤ 50 - a, b ≤ n - c ≤ 10000000
| |
Sample Input | Output for Sample Input |
2 | Case #1: No cycle found. |
大体思路:使用二分法求解,对于每一个猜测值mid,只需要判断是否存在平均值小于mid的回路。如何判断呢?假设存在一个包含K条边的回路,回路上个条边的权值为w1,w2
,,wk,那么平均值小于mid意味着w1+w2+w3+.....<K*mid即:(w1-mid)+(w2-mid)+(w3-mid)+....+(wk-mid)<0;换句话说,只要把每条边(a,b)的权值w(a,b)换成w(a,b)-mid,再判断是否有负权的回路即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MAXN 100
struct node
{
int to,next;
double dis;
}edge[MAXN*MAXN];
bool in[MAXN];
int head[MAXN],en;
int n,m,cnt[MAXN];
double dis[MAXN];
void add(int u,int v,double dis)
{
edge[en].to=v;
edge[en].dis=dis;
edge[en].next=head[u];
head[u]=en++;
}
bool spfa()
{
queue<int> q;
for(int i=1;i<=n;i++)
{
dis[i]=0;
cnt[i]=0;
in[i]=true;
q.push(i);
}
while(!q.empty())
{
int u=q.front();
in[u]=false;
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(dis[u]+edge[i].dis<dis[v])
{
dis[v]=dis[u]+edge[i].dis;
if(!in[v])
{
q.push(v);
in[v]=true;
if(++cnt[v]>=n)
return false;
}
}
}
}
return true;
}
bool jud(double x)
{
bool fg=0;
for(int i=1;i<=n;i++)
for(int j=head[i];j!=-1;j=edge[j].next)
edge[j].dis-=x;
if(!spfa()) fg=1;
for(int i=1;i<=n;i++)
for(int j=head[i];j!=-1;j=edge[j].next)
edge[j].dis+=x;
return fg;
}
int main()
{
int cs;
scanf("%d",&cs);
for(int t=1;t<=cs;t++)
{
int u,v;
double x;
double l=INF,r=0,mid;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));en=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%lf",&u,&v,&x);
add(u,v,x);
l=min(l,x);
r=max(r,x);
}
printf("Case #%d: ",t);
if(!jud(r+1))
{
printf("No cycle found.\n");
}
else
{
while(r-l>eps)
{
mid=l+(r-l)/2;
if(jud(mid))
r=mid;
else
l=mid;
}
printf("%.2lf\n",r);
}
}
return 0;
}