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 }