这道题教会我们一个道理靠谁也不如靠自己。
当时学长已经讲了,然而一脸懵逼,好吧,上网搜题解,二脸懵逼,于是自己动手,丰衣足食。自己推!
首先就是建模了,这道题谁与谁之间建模已经十分明了,超级源点,超级汇点没跑,重点在权值,首先,依照题意,是“舍弃”,因此基本确认为最小割,那么最小割从哪里割,就是我们每个人都雇佣所赚的钱(由样例可知,实际上是2倍所赚的钱,以下省略“*2”,简称合作金),但先不必算雇佣金,在一开始先只考虑赚钱,那么先说最简单的,两个人都雇佣,那么我们所赚的钱为两人合作金-雇佣两人所花的钱,那么我们割掉的边的流量就应当是雇佣金了,于是乎,连向终点的流量get,即为雇佣金。
于是我们happy的继续推,如果这两个人我都不雇佣,那么我损失的就是雇佣他俩所赚的钱了,而我割的边的流量就是合作金,因为两人均摊,因此不必*2。
最后,也就是个人认为比较复杂的就是一个雇佣一个不雇佣的情况,那么比起两人一起合作所产生的合作金我少的就是两倍合作金+敌对公司让我减少的一倍合作金+我所雇佣的那个人的雇佣金,由之前我们可知我割掉雇佣的那个人与汇点的时候已减少雇佣金,我割掉不雇佣的人与源点的时候以减去一倍合作金,于是乎,剩下的就是两倍合作金了,这就是两人之间的流量,记得开双向哈。
总的来说就是这样,由简到难,由已知边的流量去推未知边的流量,找准总值为关键,实在不行就列个方程,怎样也能搞出来。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 int n,s,zz=1,t; 10 long long co[1015],a[1015]; 11 struct ro{ 12 int to,from; 13 int next; 14 long long l; 15 }road[9000000]; 16 void build(int x,int y,long long z){ 17 zz++; 18 road[zz].l=z; 19 road[zz].to=y; 20 road[zz].from=x; 21 road[zz].next=a[x]; 22 a[x]=zz; 23 zz++; 24 road[zz].to=x; 25 road[zz].from=y; 26 road[zz].next=a[y]; 27 road[zz].l=0; 28 a[y]=zz; 29 } 30 long long sum[1005]; 31 long long deep[1005],cur[1015],cur2[1015]; 32 bool bfs(){ 33 memset(deep,0,sizeof(deep)); 34 queue<int> q1; 35 q1.push(s); 36 deep[s]=1; 37 while(!q1.empty()) 38 { 39 int x=q1.front(); 40 q1.pop(); 41 for(int i=a[x];i>0;i=road[i].next) 42 { 43 int y=road[i].to; 44 if(road[i].l>0&&(!deep[y])) 45 { 46 deep[y]=deep[x]+1; 47 q1.push(y); 48 } 49 } 50 } 51 if(!deep[t])return 0; 52 return 1; 53 } 54 long long dfs(int x,long long sum){ 55 if(x==t||!sum) return sum; 56 for(int i=cur[x];i>0;i=road[i].next) 57 { 58 cur[x]=i; 59 int y=road[i].to; 60 if(road[i].l>0&&deep[y]==deep[x]+1) 61 { 62 int k=dfs(y,min(sum,road[i].l)); 63 if(k) 64 { 65 road[i].l-=k; 66 road[i^1].l+=k; 67 return k; 68 } 69 } 70 } 71 return 0; 72 } 73 long long work(){ 74 long long ans=0; 75 memcpy(cur2,a,sizeof(a)); 76 while(bfs()) 77 { 78 int x; 79 memcpy(cur,cur2,sizeof(cur2)); 80 while(x=dfs(s,0x7fffffff)) 81 { 82 ans+=x; 83 } 84 } 85 return ans; 86 } 87 long long summ; 88 int main(){ 89 scanf("%d",&n); 90 t=n+1; 91 for(int i=1;i<=n;i++) 92 { 93 scanf("%lld",&co[i]); 94 } 95 for(int i=1;i<=n;i++) 96 { 97 for(int j=1;j<=n;j++) 98 { 99 long long x; 100 scanf("%lld",&x); 101 if(x)build(i,j,x*2); 102 sum[i]+=x; 103 } 104 } 105 for(int i=1;i<=n;i++) 106 { 107 build(s,i,sum[i]); 108 build(i,t,co[i]); 109 summ+=sum[i]; 110 } 111 printf("%lld\n",summ-work()); 112 //while(1); 113 return 0; 114 }
来源:http://www.cnblogs.com/liutianrui/p/7265808.html