Uva 11090 最短路径

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2031

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, NN test cases follow. Each one starts with two numbers n and mm 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
2 1
1 2 1
2 2
1 2 2
2 1 3

Case #1: No cycle found.
Case #2: 2.50

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

大体思路:使用二分法求解,对于每一个猜测值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;  
} 


你可能感兴趣的:(Uva 11090 最短路径)