这道题教会我们一个道理靠谁也不如靠自己。
当时学长已经讲了,然而一脸懵逼,好吧,上网搜题解,二脸懵逼,于是自己动手,丰衣足食。自己推!
首先就是建模了,这道题谁与谁之间建模已经十分明了,超级源点,超级汇点没跑,重点在权值,首先,依照题意,是“舍弃”,因此基本确认为最小割,那么最小割从哪里割,就是我们每个人都雇佣所赚的钱(由样例可知,实际上是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