POJ 2987 最大权闭合图

题意:

 一个公司打算解雇一些员工,已知解雇每个人的收益值(可能为负)。解雇某一个人后,他的下属也将被解雇,求最大收益是多少,在取得最大收益时需要解雇多少人。

题解:

建图不多啰嗦,挺裸的~

求最少的割边数目,可以从源点对残量网络进行一次DFS,每个割都会将源点和汇点隔开,所以从源点DFS下去一定会碰到某个割dfs停止,这时遍历过的点数最少的裁员数目。那种直接找满流边的做法是显然不对的奥~

 

ps:总是wa盛怒之下,把所有int替换了ac了。。。

 

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <iostream>
  5 
  6 #define N 100100
  7 #define M 3000000
  8 #define INF 100000000
  9 
 10 using namespace std;
 11 //理解最大权闭合图的最小割的含义 
 12 __int64 head[N],to[M],next[M],len[M],sum,n,m,cnt,S,T,layer[N],q[M<<2],num,ans;
 13 bool vis[N];
 14 
 15 inline void add(__int64 u,__int64 v,__int64 wp)
 16 {
 17     to[cnt]=v; len[cnt]=wp; next[cnt]=head[u]; head[u]=cnt++;
 18     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
 19 }
 20 
 21 void read()
 22 {
 23     memset(head,-1,sizeof head);cnt=0;
 24     S=0,T=n+1;sum=0;
 25     for(__int64 i=1,a;i<=n;i++)
 26     {
 27         scanf("%I64d",&a);
 28         if(a>=0)
 29         {
 30             sum+=a;
 31             add(S,i,a);
 32         }
 33         else add(i,T,-a);
 34     }
 35     for(__int64 i=1,a,b;i<=m;i++)
 36     {
 37         scanf("%I64d%I64d",&a,&b);
 38         add(a,b,INF);
 39     }
 40 }
 41 
 42 bool bfs()
 43 {
 44     memset(layer,-1,sizeof layer);
 45     __int64 h=1,t=2,sta;
 46     q[1]=S; layer[S]=0;
 47     while(h<t)
 48     {
 49         sta=q[h++];
 50         for(__int64 i=head[sta];~i;i=next[i])
 51             if(len[i]&&layer[to[i]]<0)
 52             {
 53                 layer[to[i]]=layer[sta]+1;
 54                 q[t++]=to[i];
 55             } 
 56     }
 57     return layer[T]!=-1;
 58 }
 59 
 60 __int64 find(__int64 u,__int64 cur_flow)
 61 {
 62     if(u==T) return cur_flow;
 63     __int64 result=0,tmp;
 64     for(__int64 i=head[u];~i&&result<cur_flow;i=next[i])
 65         if(len[i]&&layer[to[i]]==layer[u]+1)
 66         {
 67             tmp=find(to[i],min(cur_flow-result,len[i]));
 68             len[i]-=tmp; len[i^1]+=tmp; result+=tmp;
 69         }
 70     if(!result) layer[u]=-1;
 71     return result;
 72 }
 73 
 74 void dinic()
 75 {
 76     ans=0;
 77     while(bfs()) ans+=find(S,INF);
 78     
 79 }
 80 
 81 void dfs(__int64 u)
 82 {
 83     if(u==T) return;
 84     vis[u]=true;
 85     for(__int64 i=head[u];~i;i=next[i])
 86         if(!vis[to[i]]&&len[i]>0)
 87             dfs(to[i]);
 88 }
 89 
 90 int main()
 91 {
 92     while(scanf("%I64d%I64d",&n,&m)!=EOF)
 93     {
 94         read();
 95         dinic();
 96         num=0;
 97         memset(vis,0,sizeof vis);
 98         dfs(S);
 99         for(__int64 i=1;i<=n;i++)
100             if(vis[i]) num++;
101         printf("%I64d %I64d\n",num,sum-ans);
102     }
103     return 0;
104 }

 

 

posted @ 2013-01-07 23:27  proverbs  阅读(183)  评论(0编辑  收藏  举报