• poj3621 Sightseeing Cows --- 01分数规划


    典型的求最优比例环问题

    參考资料:

    http://blog.csdn.net/hhaile/article/details/8883652


    此题中,给出每一个点和每条边的权值,求一个环使 ans=∑点权/∑边权 最大。

    由于题目要求一个环,并且必定是首尾相接的一个我们理解的纯粹的环,不可能是其它样子的环,

    所以我们能够把一条边和指向的点看做总体处理。

    上面方程能够化为:ans×e[i]-p[i]=0

    以它为边权二分答案,spfa求负环,有负环则该ans可行,增大下界。

    若一直不可行,则无解。


    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #define inf 0x3f3f3f3f
    using namespace std;
    #define N 1010
    #define M 5010
    
    struct node
    {
        int next,v,w;
    }e[M];
    int n,m,h,head[N],p[N],inq[N],outq[N];
    double d[N];
    
    void addedge(int a,int b,int c)
    {
        e[h].v=b;
        e[h].w=c;
        e[h].next=head[a];
        head[a]=h++;
    }
    
    bool spfa(int s,double ans)
    {
        int i,cnt=0;
        for(i=0;i<=n;i++)
            d[i]=2000000000;
        memset(inq,0,sizeof inq);
        memset(outq,0,sizeof outq);
        d[s]=0;
        inq[s]=1;
        queue<int> q;
        q.push(s);
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            inq[x]=0;
            outq[x]++;
            cnt++;
            if(outq[x]>n) return 0;
            if(cnt>(n+m)<<1) return 0;
            for(i=head[x];i!=-1;i=e[i].next)
            {
                int v=e[i].v;
                if(d[v]>d[x]+ans*e[i].w-p[v])
                {
                    d[v]=d[x]+ans*e[i].w-p[v];
                    if(!inq[v])
                        q.push(v);
                }
            }
        }
        return 1;
    }
    
    
    int main()
    {
        int a,b,c,i;
        double le,ri,mid;
        while(~scanf("%d%d",&n,&m))
        {
            memset(head,-1,sizeof head);
            h=0;
            for(i=1;i<=n;i++)
                scanf("%d",&p[i]);
            for(i=0;i<m;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                addedge(a,b,c);
            }
            le=0;ri=1010;
            double ans=0;
            while(ri-le>1e-5)
            {
                mid=(le+ri)/2.0;
                if(spfa(1,mid))
                {
                    ri=mid;
                }
                else
                {
                    ans=mid;
                    le=mid;
                }
            }
            printf("%.2lf
    ",ans);//G++要用%f才干A
        }
        return 0;
    }
    


  • 相关阅读:
    vue——学习笔记
    工作笔记——上传图片
    前端调试利器——BrowserSync
    工作笔记——一些常用函数的封装
    【html、CSS、javascript-3】几个基本元素
    【html、CSS、javascript-2】CSS基础
    【html、CSS、javascript-1】html基础
    【python之路37】with上下文管理
    【python之路36】进程、线程、协程相关
    【python之路35】FTP文件断电续传作业
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3918968.html
Copyright © 2020-2023  润新知