题目大意:
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 ",sum-F.maxFlow()); } return 0; }