bzoj2039: [2009国家集训队]employ人员雇佣(最小割)

2039: [2009国家集训队]employ人员雇佣

题目:传送门

题解:

   这一题一开始看前面以为是和最大获利一样。。

   双倍经验啊!!!美滋滋~

   然后发现自己漏了一个条件,还有敌对公司这种操作666~

   然后认真的再想了一下,正权和-最小割!!!

   本蒟蒻是这样理解的:

   我们把每个人的总获利(把二维转换为一维累加)和st连边

   雇佣的花费向ed连

   两两员工之间连2*E[i][j]的边,这个是关键。

   我们在跑最小割的时候,如果我们把i,j分离,其实是舍去了两倍收益的(敌对公司)

   这样一想,正权和-最小割输出答案。

   一A美滋滋~

代码:

  

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #define N 1100
  7 #define qread(x)x=read();
  8 using namespace std;
  9 typedef long long LL;
 10 inline int read()
 11 {
 12     int f=1,x=0;char ch;
 13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 15     return f*x;
 16 }
 17 struct node
 18 {
 19     int x,y,next,other;
 20     LL c;
 21 }a[2100000];int last[1100000],len;
 22 void ins(int x,int y,LL c)
 23 {
 24     int k1,k2;
 25     len++;k1=len;
 26     a[len].x=x;a[len].y=y;a[len].c=c;
 27     a[len].next=last[x];last[x]=len;
 28     
 29     len++;k2=len;
 30     a[len].x=y;a[len].y=x;a[len].c=0;
 31     a[len].next=last[y];last[y]=len;
 32     
 33     a[k1].other=k2;
 34     a[k2].other=k1;
 35 }
 36 int n,st,ed,head,tail;
 37 int s[1100000];
 38 LL d[1100000];
 39 int list[1100000],h[1100000];
 40 bool bt_h()
 41 {
 42     memset(h,0,sizeof(h));h[st]=1;
 43     list[1]=st;head=1;tail=2;
 44     while(head!=tail)
 45     {
 46         int x=list[head];
 47         for(int k=last[x];k;k=a[k].next)
 48         {
 49             int y=a[k].y;
 50             if(h[y]==0 && a[k].c>0)
 51             {
 52                 h[y]=h[x]+1;
 53                 list[tail++]=y;
 54             }
 55         }
 56         head++;
 57     }
 58     if(h[ed]>0)return true;
 59     else return false;
 60 }
 61 int find_flow(int x,LL flow)
 62 {
 63     if(x==ed)return flow;
 64     LL s=0,t;
 65     for(int k=last[x];k;k=a[k].next)
 66     {
 67         int y=a[k].y;
 68         if((h[y]==h[x]+1) && a[k].c>0  && s<flow)
 69         {
 70             t=find_flow(y,min(a[k].c,flow-s));
 71             s+=t;
 72             a[k].c-=t;a[a[k].other].c+=t;            
 73         }
 74     }
 75     if(s==0)h[x]=0;
 76     return s;
 77 }
 78 int main()
 79 {
 80     qread(n);st=0;ed=n+1;
 81     int sum=0;
 82     len=0;memset(last,0,sizeof(last));
 83     for(int i=1;i<=n;i++)
 84     {
 85         LL x;
 86         scanf("%lld",&x);
 87         ins(i,ed,x);
 88     }
 89     for(int i=1;i<=n;i++)
 90     {
 91         for(int j=1;j<=n;j++)
 92         {
 93             LL x;
 94             scanf("%lld",&x);
 95             if(i==j)continue;
 96             sum+=x;d[i]+=x;
 97             ins(i,j,x*2);
 98         }
 99     }
100     for(int i=1;i<=n;i++)ins(st,i,d[i]);
101     LL ans=0;
102     while(bt_h())ans+=find_flow(st,999999999);
103     printf("%lld",sum-ans);
104     return 0;
105 }

  

原文地址:https://www.cnblogs.com/CHerish_OI/p/8093598.html