Codevs 1183 泥泞的道路

1183 泥泞的道路
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
传送门
题目描述 Description
CS有n个小区,并且任意小区之间都有两条单向道路(a到b,b到a)相连。因为最近下了很多暴雨,很多道路都被淹了,不同的道路泥泞程度不同。小A经过对近期天气和地形的科学分析,绘出了每条道路能顺利通过的时间以及这条路的长度。
现在小A在小区1,他希望能够很顺利地到达目的地小区n,请帮助小明找出一条从小区1出发到达小区n的所有路线中(总路程/总时间)最大的路线。请你告诉他这个值。
输入描述 Input Description
第一行包含一个整数n,为小区数。
接下来n*n的矩阵P,其中第i行第j个数表示从小区i到小区j的道路长度为Pi,j。第i行第i个数的元素为0,其余保证为正整数。
接下来n*n的矩阵T,第i行第j个数表示从小区i到小区j需要的时间Ti,j。第i行第i个数的元素为0,其余保证为正整数。
输出描述 Output Description
写入一个实数S,为小区1到达n的最大答案,S精确到小数点后3位。
样例输入 Sample Input
3
0 8 7
9 0 10
5 7 0
0 7 6
6 0 6
6 2 0
样例输出 Sample Output
2.125
数据范围及提示 Data Size & Hint
【数据说明】
30%的数据,n<=20
100%的数据,n<=100,p,t<=10000
分类标签 Tags
二分法 最短路 图论

/*
二分答案+spfa最长路判正环.
好题.
先处理出一个ans.
然后二分答案.
判出现正环或者能跑通整个图. 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 101
#define MAXM 200001
using namespace std;
double g[MAXN][MAXN],s[MAXN][MAXN],tot,ans,dis[MAXN],t[MAXN][MAXN];
int n,m;
bool b[MAXN];
bool spfa()
{
    memset(b,0,sizeof(b));
    memset(dis,-0x3f,sizeof(dis));
    int q[MAXM],c[MAXN]={0};
    int head=0,tail=1;c[1]=1;
    q[tail]=1,dis[1]=0,b[1]=true;
    while(head<tail)
    {
        head++;
        int u=q[head];
        for(int i=1;i<=n;i++)
          {
            if(s[u][i]&&dis[i]<g[u][i]+dis[u])
            {
                dis[i]=g[u][i]+dis[u];
                if(!b[i])
                {
                b[i]=true;
                q[++tail]=i;
                c[i]+=1;
                if(c[i]>n) return true;
                }
            }
          }
        b[u]=false;
    }
    if(dis[n]>0) return true;
    return false;
}
bool slove(double x)
{
    memset(g,0,sizeof(g));
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        {
            g[i][j]=s[i][j]-x*t[i][j];
        }
    if(spfa()) return true;
    return false;
}
double erfen()
{
    double mid,l=0,r=100000;
    while(r-l>0.0001)
    {
        mid=(l+r)/2;
        if(slove(mid)){
            l=mid,ans=mid;
        }
        else r=mid;
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        scanf("%lf",&s[i][j]);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
        scanf("%lf",&t[i][j]);
    printf("%.3lf",erfen());
    return 0;
}
posted @ 2016-07-08 17:42  nancheng58  阅读(117)  评论(0编辑  收藏  举报