zoukankan      html  css  js  c++  java
  • hdu3879 最大权闭合图

     若a,b 2点能够相连,那么可以得到ci的价值,也就是说a,b是得到c的前提条件,对于每一个点,又有耗费。

    对于本题,先求出最多能够得到的利益有多少,最小割=未被 选的用户的收益之和 + 被选择的站点的成本之和,要尽量的小。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #define INF 99999999
    using namespace std;
    const int maxn = 61000;
    struct node
    {
        int to;
        int v;
        int flag;
        int next;
    }edge[500001];
    int pre[maxn],index,vis[maxn],S,T;
    int min(int x,int y){return x<y?x:y;}
    void add(int x,int y,int z)
    {
        edge[index].to=y;
        edge[index].v=z;
        edge[index].flag=index+1;
        edge[index].next=pre[x];
        pre[x]=index++;
        edge[index].to=x;
        edge[index].v=0;
        edge[index].flag=index-1;
        edge[index].next=pre[y];
        pre[y]=index++;
    }
    int dfs(int u,int low)
    {
        int i,used=0;
        if(u==T)
            return low;
        for(i=pre[u];i!=-1&&used<low;i=edge[i].next)
        {
            if(vis[edge[i].to]==vis[u]+1&&edge[i].v>0)
            {
                int a=dfs(edge[i].to,min(edge[i].v,low-used));
                if(!a)continue;
                edge[i].v-=a;
                edge[edge[i].flag].v+=a;
                used+=a;
            }
        }
        if(!used)
            vis[u]=-1;
        return used;
    }
    bool BFS()
    {
        memset(vis,-1,sizeof(vis));
        queue<int>q;
        int i;
        vis[0]=0;
        q.push(0);
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            for(i=pre[t];i!=-1;i=edge[i].next)
            {
                if(edge[i].v&&vis[edge[i].to]<0)
                {
                    vis[edge[i].to]=vis[t]+1;
                    q.push(edge[i].to);
                }
            }
        }
        if(vis[T]>0)
            return true;
        return false;
    }
    int main()
    {
        int n,m,s,t,i;
        while(~scanf("%d%d",&n,&m))
        {
            index=1;
            memset(pre,-1,sizeof(pre));
            for(i=1;i<=n;i++)
            {
                int x;
                scanf("%d",&x);
                add(0,i,x);
            }
            int sum=0;
            for(i=1;i<=m;i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add(x,n+i,INF);
                add(y,n+i,INF);
                add(n+i,n+m+1,z);
                sum+=z;
            }
            int ans=0;
            S=0,T=n+m+1;
            while(BFS())
            {
                int a=dfs(0,INF);
                if(!a)break;
                ans+=a;
            }
            printf("%d
    ",sum-ans);
        }
    }
    分析:

    把每个用户和每个站点都看成一个顶点。建立网络,从源点S向每个用户连接一条容量为收益的有向边,每个用户向相关的两个站点连接一条容量为无穷大的 有向边,每个站点向汇点T连接一条容量为成本的有向边。求出网络最小割集的容量就是Maxflow=(未被选的用户的收益之和 + 被选择的站点的成本之和)。设Total为所有用户的收益之和,我们要求的是(被选的用户的收益之和 – 被选择的站点的成本之和),恰好等于Total – Maxflow,就是最大收益。

    为什么是这样的?因为任何一个可行割集对应了一个满足条件的方案,具体来说被选择的顶点就是S集合中的顶点,而割集对应了cut=(未被 选的用户的收益之和 + 被选择的站点的成本之和),我们为了要求的(被选的用户的收益之和 – 被选择的站点的成本之和)= Total – cut尽量大,Total一定,所以要让cut尽量小,直至最小割集。

  • 相关阅读:
    node.js 实际应用记录
    常用数组操作方法 包含es6语法
    JavaScript获取获取屏幕、浏览器窗口 ,浏览器,网页高度、宽度方法汇总
    vue-cli脚手架发布项目进行build压缩时遇到的问题
    路由传参
    vue 点击新的路由<router-link to=‘’></router-link>时 同时嵌套一个新网页
    vue-cli 里 利用mockjs 实现模拟后台数据并成功请求
    vue2.0 实现click点击当前li,动态切换class
    vue 动态获取浏览器内容高度并赋值给元素
    在vue中给列表中的奇数行添加class
  • 原文地址:https://www.cnblogs.com/sweat123/p/4918830.html
Copyright © 2011-2022 走看看