P3410 /// 最大流最小割

题目大意:

https://www.luogu.org/problemnew/show/P3410

题解 https://www.cnblogs.com/2020pengxiyue/p/9463055.html

源点s到各任务的边权为利益

各任务需要的职工到汇点t的边权为花费

当某一任务的 利益>=花费 时,求得的最大流为完成该任务需要的花费(1)

当某一任务的 利益<花费 时,求得的最大流为完成该任务所得的利益(2)

用总的利益减去最大流得到的

对(1)来说得到的是该任务的纯利

对(2)来说得到的是0 即不做该任务

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;

const int N=205;

int n,m,w[N],p[N];
vector <int> vec[N];

struct MAXFLOW {
    struct NODE { int to,cap,rev; };
    vector <NODE> G[N];
    int lev[N], iter[N];
    int s,t;
    void addE(int u,int v,int cap) {
        G[u].push_back((NODE){v,cap,G[v].size()});
        G[v].push_back((NODE){u,0,G[u].size()-1});
    }
    void BFS(int s) {
        memset(lev,-1,sizeof(lev));
        queue<int>q;
        q.push(s); lev[s]=0;
        while(!q.empty()) {
            int u=q.front(); q.pop();
            for(int i=0;i<G[u].size();i++) {
                NODE &v=G[u][i];
                if(v.cap>0 && lev[v.to]<0)
                    lev[v.to]=lev[u]+1, q.push(v.to);
            }
        }
    }
    int DFS(int u,int t,int f) {
        if(u==t) return f;
        for(int &i=iter[u];i<G[u].size();i++) {
            NODE &v=G[u][i];
            if(v.cap>0 && lev[u]<lev[v.to]) {
                int d=DFS(v.to,t,min(f,v.cap));
                if(d>0) {
                    v.cap-=d;
                    G[v.to][v.rev].cap+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    int maxFlow() {
        int flow=0;
        while(1) {
            BFS(s);
            if(lev[t]<0) return flow;
            memset(iter,0,sizeof(iter));
            while(1) {
                int f=DFS(s,t,INF); 
                if(f>0) flow+=f;
                else break;
            } 
        }
    }
}F;

int main()
{
    while(~scanf("%d%d",&n,&m)) {
        int sum=0, tmp;
        for(int i=1;i<=n;i++) {
            scanf("%d",&p[i]);
            sum+=p[i]; vec[i].clear();
            while(~scanf("%d",&tmp)&&tmp)
                vec[i].push_back(tmp);
        }
        for(int i=1;i<=m;i++) scanf("%d",&w[i]);
        int node=n+m;
        F.s=1+node, F.t=2+node;
        for(int i=1;i<=n;i++) {
            F.addE(F.s,i,p[i]);
            for(int j=0;j<vec[i].size();j++)
                F.addE(i,vec[i][j]+n,INF);
        }
        for(int i=n+1;i<=n+m;i++) F.addE(i,F.t,w[i-n]);
        printf("%d\n",sum-F.maxFlow());
    }

    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/zquzjx/p/10276135.html