题意:公司要裁员,每个员工被裁掉之后都会有一定的收益(正或者负),有一些员工之间有限制关系,就是裁掉谁之前必须要先裁掉另一个人,问公司的最大收益和最大收益前提下的最小裁员人数?(copy题意)
想法:一看就是最大权闭合,直接可以算出最大的收益,关键是输出最小的裁员人数,可以从残余网络里面去找,当残余网络里面的一条边,有正的权值时说明了两种可能,一种是source->(+a)的边权大于零,表示我不要这个人可以赚钱,所以a和他相连的都要开除,(-a)->sink的边权大于零,表示a可以赚很多钱以保证我不开除他的上司,我也可以赚钱。
还有一个就是建边的问题,我是这样理解的,a的前提是b那么b就是删除a的基础,那么a的地位显然比b要重要,所以a->b。
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#define inf 0x7fffffff
using namespace std;
const int N=50000+20;
const int M=60000+20;
int n,m,val[N];
long long sum;
int s,t,num;
int vis[N];
struct node
{int v,next;int flow;
}e[M*2];
int head[N],cnt;
class DINIC
{public:int spath(){queue<int>q;while(!q.empty()) q.pop();memset(dis,-1,sizeof(dis));dis[s]=0;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i+1;i=e[i].next){int v=e[i].v;if(dis[v]==-1&&e[i].flow>0){dis[v]=dis[u]+1;q.push(v);}}}return dis[t]!=-1;}int MIN(int x,int y){if(x<y) return x;return y;}int dfs(int u,int flow){if(u==t) return flow;int cost=0;for(int i=head[u];i+1;i=e[i].next){int v=e[i].v;if(dis[v]==dis[u]+1&&e[i].flow>0){int mmin=dfs(v,MIN(e[i].flow,flow-cost));if(mmin>0){e[i].flow-=mmin;e[i^1].flow+=mmin;cost+=mmin;if(flow==cost) break;}else dis[v]=-1;}} return cost;}long long result(){long long res=0;while(spath()){res+=dfs(s,inf);}return res;}private:int dis[N];
}dinic;
void qianxiang_Init()
{memset(head,-1,sizeof(head));cnt=0;
}
void add(int a,int b,int c)
{e[cnt].v=b;e[cnt].flow=c;e[cnt].next=head[a];head[a]=cnt++;e[cnt].v=a;e[cnt].flow=0;e[cnt].next=head[b];head[b]=cnt++;
}
void Input()
{for(int i=1;i<=n;i++)scanf("%d",&val[i]); for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);add(a,b,inf);}
}
void dfs(int u)
{if(u==t) return;vis[u]=1;for(int i=head[u];i+1;i=e[i].next){int v=e[i].v;if(!vis[v]&&e[i].flow>0){num++;dfs(v);}}return;
}
void build_map()
{s=0;t=n+1;sum=0;for(int i=1;i<=n;i++){if(val[i]>=0) {add(s,i,val[i]);sum+=val[i];}else add(i,t,-val[i]);}
}
void treatment()
{build_map();long long profit=dinic.result();num=0;memset(vis,0,sizeof(vis));dfs(s);printf("%d %lld\n",num,sum-profit);
}
int main()
{while(~scanf("%d %d",&n,&m)){qianxiang_Init();Input();treatment();}return 0;
}