• poj 3621 二分+spfa判负环


    http://poj.org/problem?id=3621

    求一个环的{点权和}除以{边权和},使得那个环在所有环中{点权和}除以{边权和}最大。

    0/1整数划分问题

    令在一个环里,点权为v[i],对应的边权为e[i], 
    即要求:∑(i=1,n)v[i]/∑(i=1,n)e[i]最大的环(n为环的点数), 
    设题目答案为ans, 
    即对于所有的环都有 ∑(i=1,n)(v[i])/∑(i=1,n)(e[i])<=ans 
    变形得ans* ∑(i=1,n)(e[i])>=∑(i=1,n)(v[i]) 
    再得 ∑(i=1,n)(ans*e[i]-v[i]) >=0 
    稍分析一下,就有: 
    当k<ans时,就存在至少一个环∑(i=1,n)(k*e[i]-v[i])<0,即有负权回路(边权为k*e[i]-v[i]); 
    当k>=ans时,就对于所有的环∑(i=1,n)(k*e[i]-v[i])>=0,即没有负权回路。 
    然后我们就可以使新的边权为k*e[i]-v[i],用spfa来判断负权回路,二分ans。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define RD(x) scanf("%d",&x)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define clr0(x) memset(x,0,sizeof(x))
    #define clr1(x) memset(x,-1,sizeof(x))
    using namespace std;
    typedef long long LL;
    const int maxn = 1005,maxm = 105;
    const double eps = 1e-3;
    const int inf = 0x7fffffff;
    int v[maxn];
    struct edge{
        int v,w,next;
        edge(){};
        edge(int vv,int ww,int nnext):v(vv),w(ww),next(nnext){};
    }e[maxn*5];
    int head[maxn],vis[maxn],_v[maxn],cnt[maxn],ecnt,n,m;
    double dist[maxn];
    void add(int u,int v,int w)
    {
        e[ecnt] = edge(v,w,head[u]);
        head[u] = ecnt++;
    }
    void init()
    {
        for(int i = 1;i <= n;++i)
            RD(_v[i]);
        ecnt = 0;
        clr1(head);//判负环的初始化
        int u,v,w;
        while(m--){
            RD3(u,v,w);
            add(u,v,w);
        }
        return ;
    }
    bool spfa(double mid)
    {
        clr0(vis),clr0(cnt);
        fill(dist,dist + n + 1,inf);
        dist[1] = 0;
        queue<int> q;
        q.push(1);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = false;
            cnt[u]++;
            if(cnt[u] > n)
                return true;
            for(int i = head[u];i != -1;i = e[i].next){
                int v = e[i].v;
                double tmp = mid*e[i].w - _v[v];//"边权"
                if(dist[u] + tmp < dist[v]){
                    dist[v] = dist[u] + tmp;
                    if(!vis[v]){
                        vis[v] = true;
                        q.push(v);
                    }
                }
            }
        }
        return false;
    }
    void work()
    {
        double l = 0,r = 10000,mid,ans;
        while(r - l > eps){
            mid = (l + r)/2;
            if(spfa(mid)){
                ans = mid;
                l = mid - 0.000001;
            }else
                r = mid + 0.000001;
        }
        printf("%.2f
    ",ans);
    }
    int main()
    {
        while(~RD2(n,m)){
            init();
            work();
        }
        return 0;
    }
    


  • 相关阅读:
    java 8 lambda函数
    java nio和io
    jetty xml解析
    使用spring框架时,使用xml还是注解
    tcp/ip基础知识
    http的session和cookie
    html相关
    form之action的绝对路径与相对路径(转载)
    MariaDB 10 (MySQL DB) 多主复制并实现读写分离
    牛刀小试MySQL学习—MySQL 双主
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4106647.html
Copyright © 2020-2023  润新知