zoukankan      html  css  js  c++  java
  • codevs1183泥泞的道路

    题意:给定一张有向稠密图和通过每条边的时间和路程,问从1到n的路程/时间 最大为多少

     

    正解:SPFA+二分答案

     

    开始做的时候,想直接跑图论,后来发现好像不对(不然数据范围怎么这么小)

    但是显然要用到图论,机智的我就想到了二分答案。

     

    考虑,假如有一个ans,那么如果存在length i / time i >=ans(i属于路径上的边),那么显然更优 ,则可发现问题可转换为如果一个答案更优,那么对于以 length i - ans*time i 为权值,重新构的图中,如果到达n的最长路不小于n,显然答案可以更优,只需要二分答案就可以了.另外如果有正权环显然是可以的  

     

    唯独要注意的是,精度要求要满足题意,显然不能只分到第三位小数就停了,那样的话会gi

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    const int MAXN = 101;
    int n;
    int tim[MAXN][MAXN],s[MAXN][MAXN];
    long double ju[MAXN][MAXN];
    double dis[MAXN];
    bool vis[MAXN];
    int num[MAXN];//记录经过次数,判环
    long double ans;
    //二分答案+SPFA
    
    queue<int>q;
    
    inline int getint()
    {
           int w=0,q=0;
           char c=getchar();
           while((c<'0' || c>'9') && c!='-') c=getchar();
           if (c=='-')  q=1, c=getchar();
           while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
           return q ? -w : w;
    }
    
    inline bool work(long double x){//跑最长路径
        for(int i=1;i<=n;i++) dis[i]=-0x7ffffff;//置为更小的负值
        // memset(dis,0,sizeof(dis));
        ans=x;
    
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            ju[i][j]=s[i][j]-x*tim[i][j];
    
        memset(vis,0,sizeof(vis));
        memset(num,0,sizeof(num));
        while(!q.empty()) q.pop();
        
        q.push(1); vis[1]=1; dis[1]=0;
        while(!q.empty()) {
        int u=q.front();
        q.pop(); vis[u]=0;
        for(int i=1;i<=n;i++)
            if(i!=u){
            if(dis[i]<dis[u]+ju[u][i]) {
                dis[i]=dis[u]+ju[u][i];
                if(!vis[i]) {
                vis[i]=1;
                q.push(i);
                num[i]++;
                if(num[i]>=n) return true;
                }
            }
            }
        }
    
        if(dis[n]>=0) return true;//存在更优的答案
        return false;
    }
    
    int main()
    {
        n=getint();
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) s[i][j]=getint();
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) tim[i][j]=getint();
    
        long double l=0.00,r=10000.00;
        //long double jingdu=0.00001;
        long double jingdu=0.0001;
        while(r-l-jingdu>=0) {
        long double mid=l+(r-l)/2.0;
        if(work(mid)) l=mid;
        else r=mid;
        }
        printf("%.3lf",(double)l);
        return 0;
    }
    本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ 转载请注明出处,侵权必究,保留最终解释权!
  • 相关阅读:
    存储过程与事务实现转账
    win7创建虚拟无线网络
    .net制作安装包 如何生成快捷方式
    安装EFCodeFirst失败。。。。
    用VS2010自带的Library Package Manager安装EFCodeFirst出现“无法加载一个或多个请求的类型”错误的解决方法
    Java struts2
    Java spring
    Java web
    传输层
    xml
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5450505.html
Copyright © 2011-2022 走看看