• HDU 3879 Base Station(最大权闭合子图)


    经典例题,好像说可以转化成maxflow(n,n+m),暂时只可以勉强理解maxflow(n+m,n+m)的做法。

    题意:输入n个点,m条边的无向图。点权为负,边权为正,点权为代价,边权为获益,输出最大获益。

    (最大权闭合子图:图中各点的后继必然也在图中)

    构图攻略:将边看做点,

    若选某条边e[i](u,v,w),则必须选点u,v。由此构成一个有向图。也符合最大权闭合子图模型。

    对原本的边e[i](u,v,w)连3条边(S,n+i,w),(n+i,u,inf),(n+i,v,inf)。

    对原本的点v,连1条边(v,T,p[v])。

    即正权点与源点连,负权点与汇点连。

    求最大流,记所有边的正权和为sum,则sum-maxflow就是答案。

    显然,sap图的点有n+m+2,边有(n+m*3)*2。

    具体证明推导请移步前辈的论文或者别的网站也有很详细的介绍和步骤。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <set>
    #include <queue>
    using namespace std;
    
    #define ll long long
    #define MP make_pair
    
    #define mxn 56000
    #define mxe (51000*4*2)
    #define inf 1e9
    #define eps 1e-8
    
    
    struct SAP{
        int dis[mxn],pre[mxn],gap[mxn],arc[mxn];
        int f[mxe],cap[mxe];
        int head[mxn],nxt[mxe],vv[mxe],e;
        void init(){e=0;memset(head,-1,sizeof(head));}
        void add(int u,int v,int c){
            vv[e]=v,cap[e]=c,nxt[e]=head[u],head[u]=e++;
            vv[e]=u,cap[e]=0,nxt[e]=head[v],head[v]=e++;
        }
        ll max_flow(int s,int t,int n){
            int q[mxn],j,mindis;
            ll ans=0;
            int ht=0,tl=1,u,v;
            int low;
            bool found,vis[mxn];
            memset(dis,0,sizeof(dis));
            memset(gap,0,sizeof(gap));
            memset(vis,0,sizeof(vis));
            memset(arc,-1,sizeof(arc));
            memset(f,0,sizeof(f));
            q[0]=t;vis[t]=true;dis[t]=0;gap[0]=1;
            while(ht<tl){
                u=q[ht++];
                for(int i=head[u];i!=-1;i=nxt[i]){
                    v = vv[i];
                    if(!vis[v]){
                        vis[v]=true;
                        dis[v]=dis[u]+1;
                        q[tl++]=v;
                        gap[dis[v]]++;
                        arc[v]=head[v];
                    }
                }
            }
            u=s;low=inf;pre[s]=s;
            while(dis[s]<n){
                found=false;
                for(int &i=arc[u];i!=-1;i=nxt[i]){
                    if(dis[vv[i]]==dis[u]-1 && cap[i]>f[i]){
                        found=true;v=vv[i];
                        low=min(low,cap[i]-f[i]);
                        pre[v]=u;u=v;
                        if(u==t){
                            while(u!=s){
                                u=pre[u];
                                f[arc[u]]+=low;
                                f[arc[u]^1]-=low;
                            }
                            ans+=low;low=inf;
                        }
                        break;
                    }
                }
                if(found) continue;
                mindis=n;
                for(int i=head[u];i!=-1;i=nxt[i]){
                    if(mindis>dis[vv[i]] && cap[i]>f[i]){
                        mindis=dis[vv[j=i]];
                        arc[u]=i;
                    }
                }
                if(--gap[dis[u]]==0) return ans;
                dis[u]=mindis+1;
                gap[dis[u]]++;
                u=pre[u];
            }
            return ans;
        }
    }sap;
    int p[5050];
    int main(){
    	int n,m;
    	while(~scanf("%d%d",&n,&m)){
    		for(int i=1;i<=n;++i) scanf("%d",p+i);
    		ll sum = 0;
    		sap.init();
            for(int i=1;i<=m;++i){
    			int a,b,c;
    			scanf("%d%d%d",&a,&b,&c);
    			sap.add(n+m+1,n+i,c);
    			sap.add(n+i,a,inf);
    			sap.add(n+i,b,inf);
    			sum+=c;
            }
            for(int i=1;i<=n;++i)
    			sap.add(i,n+m+2,p[i]);
    		ll mf = sap.max_flow(n+m+1,n+m+2,n+m+2);
    		printf("%I64d
    ",sum-mf);
        }
        return 0;
    }
    
  • 相关阅读:
    node.js 笔记一
    mysql 错误2203 1061 及安装最后出现2003现象的解决办法
    git shell 命令大全
    Mysql常用命令行大全
    php 魔术方法 说明
    php linux 环境搭建
    Linux下源码编译安装MySQL 5.5.8
    linux 压缩解压缩命令
    ftp 命令全集
    sublime text2
  • 原文地址:https://www.cnblogs.com/nextbin/p/4067616.html
Copyright © 2020-2023  润新知