poj 2987(Firing)

来源:互联网 发布:农产品流通网络建设 编辑:程序博客网 时间:2024/06/07 22:26

题目链接:http://poj.org/problem?id=2987

题意简述:一个公司要裁人,给出裁每个人都有个盈利或者损失,如果一个人的上司被裁那么他也将被裁,现在问怎样裁才能使得公司的收益最大,最大为多少?


分析:因为这里上司和下属之间存在一个依赖关系,下属存在的前提或者是必要条件是其上司的存在,所以这满足最大闭权闭合图的性质,用最大权闭合图求解即可

这里注意:结果有可能会超过int,需用__int64或者long long

代码:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const __int64 inf = 0x3fffffffffffff;const int N = 5050;const int E = 120050;int e,head[N];int num;int dep[N],que[N],cur[N];bool vis[N];struct node{int x,y;int nxt;__int64 c;}edge[E];void addedge(int u,int v,__int64 c){edge[e].x=u;edge[e].y=v;edge[e].nxt=head[u];edge[e].c=c;head[u]=e++;edge[e].x=v;edge[e].y=u;edge[e].nxt=head[v];edge[e].c=0;head[v]=e++;}__int64 maxflow(int s,int t){int i,j,k,front,rear,top; __int64 min,res=0;while(1){memset(dep,-1,sizeof(dep));front=0;rear=0;que[rear++]=s;dep[s]=0;while(front!=rear){i=que[front++];for(j=head[i];j!=-1;j=edge[j].nxt)if(edge[j].c&&dep[edge[j].y]==-1){dep[edge[j].y]=dep[i]+1;que[rear++]=edge[j].y;}}if(dep[t]==-1)break;memcpy(cur,head,sizeof(head)); for(i=s,top=0;;){if(i==t){min=inf;for(k=0;k<top;k++)if(min>edge[que[k]].c){min=edge[que[k]].c;front=k;}for(k=0;k<top;k++){edge[que[k]].c-=min;edge[que[k]^1].c+=min;}res+=min;i=edge[que[top=front]].x;}for(j=cur[i];cur[i]!=-1;j=cur[i]=edge[cur[i]].nxt)if(dep[edge[j].y]==dep[i]+1&&edge[j].c)break;if(cur[i]!=-1){que[top++]=cur[i];i=edge[cur[i]].y;}else{if(top==0)break;dep[i]=-1;i=edge[que[--top]].x;}}}return res;}void dfs(int x){vis[x]=1;num++;for(int i = head[x];i!=-1;i=edge[i].nxt){int y = edge[i].y;if(vis[y]==false && edge[i].c)dfs(y);}}int main (){int n, m;__int64 sum , c;int i, x,y;while(scanf("%d%d",&n,&m)!=EOF){e =0;memset(head,-1,sizeof(head));sum = 0;for(i=1;i<=n;i++){scanf("%I64d",&c);if(c < 0)addedge(i,n+1,-c);else if(c > 0){addedge(0,i,c);sum+=c;}}for(i=0;i<m;i++){scanf("%d%d",&x,&y);addedge(x,y,inf);}    __int64flow = maxflow(0,n+1);num=0;memset(vis,0,sizeof(vis));dfs(0);printf("%d %I64d\n",num-1,sum-flow);}return 0;}        

原创粉丝点击