【试题来源】
2011中国国家集训队命题答辩
【问题描述】
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
【输入格式】
第一行两个正整数n,m。
接下来是六个矩阵
第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。
第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。
第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。
第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。
第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。
第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。
接下来是六个矩阵
第一个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择文科获得的喜悦值。
第二个矩阵为n行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学选择理科获得的喜悦值。
第三个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择文科获得的额外喜悦值。
第四个矩阵为n-1行m列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i+1行第j列的同学同时选择理科获得的额外喜悦值。
第五个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择文科获得的额外喜悦值。
第六个矩阵为n行m-1列 此矩阵的第i行第j列的数字表示座位在第i行第j列的同学与第i行第j+1列的同学同时选择理科获得的额外喜悦值。
【输出格式】
输出一个整数,表示喜悦值总和的最大值
【样例输入】
1 2
1 1
100 110
1
1000
1 1
100 110
1
1000
【样例输出】
1210
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模和约定】
对于10%以内的数据,n,m<=4
对于30%以内的数据,n,m<=8
对于100%以内的数据,n,m<=100 数据保证答案在2^30以内
对于100%的数据,时间限制为0.5s。
对于30%以内的数据,n,m<=8
对于100%以内的数据,n,m<=100 数据保证答案在2^30以内
对于100%的数据,时间限制为0.5s。
solution:
(ps:这个题输入是真的new bee)
网络流之最大流的最小割
用到了 翻转源汇
1.先考虑两个点的情况 设cw为同选文 cl为同选理 w为选文happiness l为选理happiness
![](https://i-blog.csdnimg.cn/blog_migrate/6f411189ff4cc02605f2fa57ca66e11f.png)
据图当 1.i 文 j 理 2.i,j同文 3.i理 j文 4.i,j同理四种情况时,把边割掉,用 总的-割的 就是答案
2.当多个点时也一样,S-i / i-T 都是i周围的 (同文+同理)/2 i-j都是 (同文+同理)(i,j的)/2
注意:
1.一开始先乘2,最后再/2,就不用double了
2.数组开10005/105 不要开10001/101
3.连的时候不要重复
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 //#define dd double 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const int N=105; 8 const int INF=(1<<31)-1; 9 inline int minn(int a,int b){return a<b?a:b;} 10 struct son 11 { 12 int v,next,u; 13 int w; 14 }; 15 son a1[1000001]; 16 int first[1000001],e; 17 inline void addbian(int u,int v,int w) 18 { 19 a1[e].u=u; 20 a1[e].v=v; 21 a1[e].w=w; 22 a1[e].next=first[u]; 23 first[u]=e++; 24 } 25 26 int dui[10000001],he,en; 27 inline void clear(){he=1;en=0;} 28 inline void push(int x){dui[++en]=x;} 29 inline int top(){return dui[he];} 30 inline void pop(){++he;} 31 inline bool empty(){return en>=he?0:1;} 32 33 int n,m,S,T; 34 int sum; 35 int wen[N][N],li[N][N]; 36 int xiawen[N][N],xiali[N][N]; 37 int youwen[N][N],youli[N][N]; 38 39 int ha[N][N]; 40 int wensum[10005],lisum[10005]; 41 42 int dep[10005]; 43 44 int bfs() 45 { 46 mem(dep,0);clear(); 47 dep[S]=1;push(S); 48 while(!empty()) 49 { 50 int now=top();pop(); 51 for(int i=first[now];i!=-1;i=a1[i].next) 52 { 53 int temp=a1[i].v; 54 if(!a1[i].w||dep[temp])continue; 55 dep[temp]=dep[now]+1; 56 push(temp); 57 if(temp==T)return 1; 58 } 59 } 60 return 0; 61 } 62 63 int dfs(int x,int val) 64 { 65 if(x==T)return val; 66 int val2=val,k; 67 for(int i=first[x];i!=-1;i=a1[i].next) 68 { 69 int temp=a1[i].v; 70 if(dep[temp]!=dep[x]+1||!val2||!a1[i].w)continue; 71 k=dfs(temp,minn(val2,a1[i].w)); 72 if(!k){dep[temp]=0;continue;} 73 a1[i].w-=k;a1[i^1].w+=k;val2-=k; 74 } 75 return val-val2; 76 } 77 78 int Dinic() 79 { 80 int ans=0; 81 while(bfs()) 82 ans+=dfs(S,INF); 83 return ans; 84 } 85 86 int main(){ 87 //freopen("nt2011_happiness.in","r",stdin); 88 //freopen("nt2011_happiness.out","w",stdout); 89 //freopen("1.txt","r",stdin); 90 mem(first,-1); 91 scanf("%d%d",&n,&m); 92 S=0;T=n*m+1; 93 for(int i=1;i<=n;++i) 94 for(int j=1;j<=m;++j) 95 {ha[i][j]=(i-1)*m+j;} 96 97 for(int i=1;i<=n;++i) 98 for(int j=1;j<=m;++j) 99 {scanf("%d",&wen[i][j]);wen[i][j]*=2;sum+=wen[i][j];} 100 for(int i=1;i<=n;++i) 101 for(int j=1;j<=m;++j) 102 {scanf("%d",&li[i][j]);li[i][j]*=2;sum+=li[i][j];} 103 104 for(int i=1;i<n;++i) 105 for(int j=1;j<=m;++j) 106 {scanf("%d",&xiawen[i][j]);xiawen[i][j]*=2;sum+=xiawen[i][j];} 107 for(int i=1;i<n;++i) 108 for(int j=1;j<=m;++j) 109 {scanf("%d",&xiali[i][j]);xiali[i][j]*=2;sum+=xiali[i][j];} 110 111 for(int i=1;i<=n;++i) 112 for(int j=1;j<m;++j) 113 {scanf("%d",&youwen[i][j]);youwen[i][j]*=2;sum+=youwen[i][j];} 114 for(int i=1;i<=n;++i) 115 for(int j=1;j<m;++j) 116 {scanf("%d",&youli[i][j]);youli[i][j]*=2;sum+=youli[i][j];} 117 // 118 for(int i=1;i<=n;++i) 119 for(int j=1;j<=m;++j) 120 { 121 wensum[ha[i][j]]=wen[i][j]+((i>1?xiawen[i-1][j]:0)+(i<n?xiawen[i][j]:0)+(j>1?youwen[i][j-1]:0)+(j<m?youwen[i][j]:0))/2; 122 lisum[ha[i][j]]=li[i][j]+((i>1?xiali[i-1][j]:0)+(i<n?xiali[i][j]:0)+(j>1?youli[i][j-1]:0)+(j<m?youli[i][j]:0))/2; 123 } 124 125 for(int i=1;i<T;++i) 126 {addbian(S,i,wensum[i]);addbian(i,S,0);} 127 for(int i=1;i<T;++i) 128 {addbian(i,T,lisum[i]);addbian(T,i,0);} 129 130 for(int i=1;i<=n;++i) 131 for(int j=1;j<=m;++j) 132 { 133 /*if(i>1) 134 { 135 addbian(ha[i][j],ha[i-1][j],(xiawen[i-1][j]+xiali[i-1][j])/2); 136 addbian(ha[i-1][j],ha[i][j],(xiawen[i-1][j]+xiali[i-1][j])/2); 137 }*/ 138 if(i<n) 139 { 140 addbian(ha[i][j],ha[i+1][j],(xiawen[i][j]+xiali[i][j])/2); 141 addbian(ha[i+1][j],ha[i][j],(xiawen[i][j]+xiali[i][j])/2); 142 } 143 /*if(j>1) 144 { 145 addbian(ha[i][j],ha[i][j-1],(youwen[i][j-1]+youli[i][j-1])/2); 146 addbian(ha[i][j-1],ha[i][j],(youwen[i][j-1]+youli[i][j-1])/2); 147 }*/ 148 if(j<m) 149 { 150 addbian(ha[i][j],ha[i][j+1],(youwen[i][j]+youli[i][j])/2); 151 addbian(ha[i][j+1],ha[i][j],(youwen[i][j]+youli[i][j])/2); 152 } 153 } 154 155 //printf("sum=%d\n",sum/2); 156 157 printf("%d",(sum-Dinic())/2); 158 //while(1); 159 return 0; 160 }