• bzoj 2039: [2009国家集训队]employ人员雇佣【最小割】


    一开始在https://www.cnblogs.com/lokiii/p/10770919.html基础上连(i,j,b[i][j])建了个极丑的图T掉了……把dinic换成isap勉强能卡过
    首先因为有正负收益所以考虑最小割,先ans=Σb,然后考虑负收益
    把割完后和s相邻的视为不选,反之视为选,选的话要付出代价a,所以连(s,i,a[i]);然后考虑如果ij一个选一个不选(这里是单向的),需要Eij的代价,所以连(i,j,E[i][j]);然后是如果一个点不选的话那么所有Eij都不会被加,所以连边(i,t,ΣE[i][j])
    跑最小割即可

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    using namespace std;
    const int N=1005;
    int n,s,t,h[N],cnt=1,le[N];
    long long b[N][N],ans;
    struct qwe
    {
        int ne,to;
        long long va;
    }e[N*N*4];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    void add(int u,int v,long long w)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        e[cnt].va=w;
        h[u]=cnt;
    }
    void ins(int u,int v,long long w)
    {
        add(u,v,w);
        add(v,u,0);
    }
    bool bfs()
    {
        memset(le,0,sizeof(le));
        queue<int>q;
        le[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=h[u];i;i=e[i].ne)
                if(e[i].va>0&&!le[e[i].to])
                {
                    le[e[i].to]=le[u]+1;
                    q.push(e[i].to);
                }
        }
        return le[t];
    }
    long long dfs(int u,long long f)
    {
        if(u==t||!f)
            return f;
        long long us=0;
        for(int i=h[u];i&&us<f;i=e[i].ne)
            if(e[i].va>0&&le[e[i].to]==le[u]+1)
            {
                long long t=dfs(e[i].to,min(e[i].va,f-us));
                e[i].va-=t;
                e[i^1].va+=t;
                us+=t;
            }
        if(!us)
            le[u]=0;
        return us;
    }
    long long dinic()
    {
        long long r=0;
        while(bfs())
            r+=dfs(s,1e11);
        return r;
    }
    int main()
    {
        n=read();
        s=0,t=n+1;
        for(int i=1;i<=n;i++)
            ins(s,i,read());
        for(int i=1;i<=n;i++)
    	{
    		long long sm=0;
            for(int j=1;j<=n;j++)
            {
                b[i][j]=read();
    			if(b[i][j])
    				sm+=b[i][j],ans+=b[i][j],ins(i,j,b[i][j]<<1);
            }
    		ins(i,t,sm);
    	}
        printf("%lld
    ",ans-dinic());
        return 0;
    }
    
  • 相关阅读:
    Java学习之路----计算圆形的面积和周长
    数据库系统的基本组成内容
    软件测试的含义以及测试的对象
    wg sync.WaitGroup执行顺序
    go channel
    字符串操作
    scanf
    py停止工作
    jira索引失败
    py kafka
  • 原文地址:https://www.cnblogs.com/lokiii/p/10772840.html
Copyright © 2020-2023  润新知