• 洛谷 P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题解


    题面

    这道题是一道标准的01分数规划:

    但是有一些细节可以优化:

    不难想到要二分一个mid然后判定图上是否存在一个环S,该环是否满足∑i=1t(Fun[vi]−mid∗Tim[ei])>0

    但是上面的算法并不好实现,所以可以将两边同时乘上-1,使式子变为i=1t(midTim[ei]Fun[vi])<0

    那么该问题就转化成了在每一个图中跑一边SPFA来寻找是否存在负环,若存在则l=mid,否则r=mid;

    #include <bits/stdc++.h>
    #define inc(a,b,c) for(register int i=a;i<=b;i+=c)
    #define ini 20010
    using namespace std;
    int n,m;
    struct littlestar{
        int from;
        int to;
        int nxt;
        double w;
    }star[ini],star2[ini];
    int head[ini],cnt,head2[ini];
    void add(int u,int v,int w)
    {
        star[++cnt].to=v;
        star[cnt].nxt=head[u];
        star[cnt].from=u;
        star[cnt].w=w;
        head[u]=cnt;
    }
    int c[ini];
    queue<int> q;
    double dis[ini];
    int vis[ini];
    int SPFA()
    {
        int tot=0;
        for(int i=1;i<=n;i++){
            q.push(i);
            dis[i]=0;
            vis[i]=1;
        }
        while(q.size()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head2[u];i;i=star2[i].nxt){
                int v=star2[i].to;
                if(dis[v]>dis[u]+star2[i].w){
                    dis[v]=dis[u]+star2[i].w;
                    if(vis[v]==0){
                        vis[v]=1;
                        q.push(v);
                        ++tot;
                        if(tot>2*(n+m)) return 0;
                    }
                }
            }
        }
        return 1;
    }
    int check(double x)
    {
        inc(1,cnt,1){
            star2[i]=star[i];
            star2[i].w=(double)star[i].w*(double)x-(double)c[star[i].from];
        }
        inc(1,n,1){
            head2[i]=head[i];
        }
        if(SPFA()){
            return 0;
        }
        else{
            return 1;
        }
    }
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int main()
    {
        n=read();
        m=read();
        inc(1,n,1) c[i]=read();
        inc(1,m,1){
            int u,v,w;
            u=read();v=read();w=read();
            add(u,v,w);
        }
        double l=0.00,r=1000010.000,mid;
        while(r-l>1e-4){
            mid=(l+r)/2;
            if(check(mid)){
                l=mid;
            }
            else{
                r=mid;
            }    
        }
        printf("%.2lf",l);
    } 
  • 相关阅读:
    C# 常用函数和方法集
    CSS选择器、优先级和匹配原理
    都是王安石惹的祸?
    世界上的一类
    历史之不可理喻片段
    历史惊人的相似
    20世纪鲜为人知的军事巨灾
    unity制作简单血条
    Unity中Instantiate物体失效问题
    Unity3D实现DoubleClick的一种方法
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11545032.html
Copyright © 2020-2023  润新知