• *


    对于⼀个已知的Ans,更新Ans的条件为:
    (P1 + P2 + …… + Pk) / (T1 + T2 + …… + Tk) > Ans
    变形后:P1 – T1 * Ans + P2 – T2 * Ans + …… + Pk – Tk * Ans > 0
    所以将Pi – Ti * Ans作为边权,⼆分Ans,跑最长路(因为要使等式左边⼤于0);注意存在正环的情况,⽤SPFA可判环,遇到环则return true(路径可⽆限延长所以⼀定⼤于0);另外注意精度,保留3位⼩数,那么⼆分的条件最好为while(r - l >0.0001)

    spfa:垂死病中惊坐起

    (手推样例推了半天没推出来....)

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define ll long long
    #define db double
    using namespace std;
    const int N = 105;
    const db eps = 0.0000001;
    const db inf = 999999.9;
    
    int n,head[N],ct[N],cnt;
    db dis[N],tim[N][N];
    bool vis[N];
    struct edge
    {
        int nxt,to;
        db wei;
    } e[N * N];
    
    void add(int a,int b,db c)
    {
        e[++cnt].nxt = head[a];
        e[cnt].to = b;
        e[cnt].wei = c;
        head[a] = cnt;
    }
    
    bool spfa(db k)
    {
        memset(ct,0,sizeof(ct));
        memset(vis,0,sizeof(vis));
        for(int i = 1; i <= n; i++)
            dis[i] = -inf;
        queue<int> q;
        q.push(1);
        dis[1]= 0;
        while(q.size())
        {
            int u = q.front();
            q.pop();
            vis[u] = false;
            ct[u]++;
            if(ct[u] == n)
                return true;
            for(int i = head[u]; i; i = e[i].nxt)
            {
                int v = e[i].to;
                db w = e[i].wei - k * tim[u][v];
                if(dis[v] < dis[u] + w)
                {
                    dis[v] = dis[u] + w;
                    if(!vis[v])
                    {
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        return dis[n] >= 0;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
            {
                db a;
                scanf("%lf",&a);
                if(a == 0)
                    continue;
                add(i,j,a);
            }
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%lf",&tim[i][j]);
        double l = 0.0,r = 10000.0;
        while(r - l > eps)
        {
            db mid = (l + r)/2;
            if(spfa(mid))
                l = mid;
            else
                r = mid;
        }
        printf("%.3lf",l);
        return 0;
    
    }
    View Code
  • 相关阅读:
    java实现字符串和LIST,MAP转换
    JAVA发送HttpClient请求及接收请求结果
    JVM内存溢出分析
    tomcat启动问题 严重: End event threw exception
    解决oracle11G密码过期问题
    查看和开启服务器端口
    tongweb安装后无法启动问题
    intellij与eclipse默认快捷键对比
    java实现pdf按页切分成图片
    ORACLE在IMP时候出现数据丢失
  • 原文地址:https://www.cnblogs.com/darlingroot/p/11289845.html
Copyright © 2020-2023  润新知