BZOJ 2039: [2009国家集训队]employ人员雇佣 最小割

这类最优化问题的本质是决策一个点选还是不选.     

那么,我们可以用最小割帮我们决策到底选还是不选(因为最小割的本质是将元素划分成两个集合的最小代价)  

然后每条边显然有断开的代价,描述出代价的关系和差量题就做出来了. 

code:  

#include <cstdio>  
#include <cstring> 
#include <string>    
#include <queue>    
#include <vector>    
#define N 1002   
#define ll long long      
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std; 
namespace net
{
    #define inf 1000000 
    struct Edge 
    {
        int u,v; 
        ll c;
        Edge(int u=0,int v=0,ll c=0):u(u),v(v),c(c){} 
    };   
    queue<int>q; 
    vector<Edge>edges;  
    vector<int>G[N]; 
    int vv[N],vis[N],d[N],s,t;       
    void add(int u,int v,ll c) 
    {
        edges.push_back(Edge(u,v,c));
        edges.push_back(Edge(v,u,0));  
        int o=edges.size();  
        G[u].push_back(o-2);
        G[v].push_back(o-1);      
    }    
    ll dfs(int x,ll cur) 
    { 
        if(x==t) 
            return cur;  
        ll an=0,flow=0;
        for(int i=vv[x];i<G[x].size();++i,++vv[x])       
        {
            Edge e=edges[G[x][i]];  
            if(e.c>0&&d[e.v]==d[x]+1) 
            {     
                an=dfs(e.v,min(cur,e.c));   
                if(an) 
                {
                    cur-=an;
                    flow+=an;            
                    edges[G[x][i]].c-=an;
                    edges[G[x][i]^1].c+=an;    
                    if(!cur) 
                        break;   
                }
            }
        }
        return flow; 
    }
    int bfs()  
    {    
        memset(vis,0,sizeof(vis));
        d[s]=0;
        vis[s]=1;
        q.push(s);
        while(!q.empty()) 
        {
            int u=q.front();
            q.pop(); 
            for(int i=0;i<G[u].size();++i) 
            {
                if(edges[G[u][i]].c>0) 
                {
                    int v=edges[G[u][i]].v;  
                    if(!vis[v]) 
                    {
                        vis[v]=1;
                        d[v]=d[u]+1;  
                        q.push(v);  
                    }
                }
            }
        }
        return vis[t]; 
    }   
    ll maxflow() 
    {
        ll re=0;
        while(bfs())   
        { 
            memset(vv,0,sizeof(vv));           
            re+=(ll)dfs(s,inf);  
        }
        return re;
    } 
};    
ll Sum[N];    
int a[N],e[N][N];          
int main() 
{
    // setIO("input");   
    int n;  
    ll sum=0;  
    scanf("%d",&n);  
    for(int i=1;i<=n;++i)  
        scanf("%d",&a[i]);                
    int s=0,t=n+1;    
    for(int i=1;i<=n;++i)        
        net::add(s,i,a[i]);   
    for(int i=1;i<=n;++i) 
    {
        for(int j=1;j<=n;++j) 
        { 
            scanf("%d",&e[i][j]);      
            Sum[i]+=e[i][j];        
            sum+=e[i][j];        
            if(e[i][j])      
                net::add(i,j,e[i][j]<<1);  
        }        
        net::add(i,t,Sum[i]);   
    }             
    net::s=s,net::t=t;   
    printf("%lld\n",sum-net::maxflow());  
    return 0; 
}   

  

posted @ 2020-03-19 09:32  EM-LGH  阅读(167)  评论(0编辑  收藏  举报