• 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
    ",sum-net::maxflow());  
        return 0; 
    }   
    

      

  • 相关阅读:
    0326系统按钮添加权限的工作(jsp权限写法)
    0321菜单数据
    ztree树的递归
    前端padding margin
    解决1像素边框问题
    水平垂直居中
    移动端css公共样式
    tap方法改良this指向
    移动端常见问题
    前端笔记(兼容)
  • 原文地址:https://www.cnblogs.com/guangheli/p/12522135.html
Copyright © 2020-2023  润新知