题意:公司要裁员,每个员工被裁掉之后都会有一定的收益(正或者负),有一些员工之间有限制关系,就是裁掉谁之前必须要先裁掉另一个人,问公司的最大收益和最大收益前提下的最小裁员人数?(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; }