bzoj2127: happiness
2127: happiness
Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1665 Solved: 811
[Submit][Status][Discuss]
Description
高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友。这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科或者理科,那么他们又将收获一些喜悦值。作为计算机竞赛教练的scp大老板,想知道如何分配可以使得全班的喜悦值总和最大。
Input
第一行两个正整数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列的同学同时选择理科获得的额外喜悦值。
Output
输出一个整数,表示喜悦值总和的最大值
Sample Input
1 2
1 1
100 110
1
1000
1 1
100 110
1
1000
Sample Output
1210
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数
仰慕一波....@Yuanziming
这题我的写法似乎非常奇怪?
看成最大权闭合子图
源点和汇点向点连边容量为收益
然后每次对于两个一起选择的情况 建立两个虚拟节点 分别表示选这两边的收益 向S和T连边
然后虚拟点向集合中的点连边..
其实感觉说的挺乱的...具体还是看代码吧
这题和3438大概算是双倍经验...我就是按照那题的写法写的
1 #include<bits/stdc++.h> 2 #define N 50005 3 #define inf 2147483647 4 #define rep(i,l,r) for(int i=l;i<=r;i++) 5 using namespace std; 6 struct node{ 7 int to,next,w; 8 }e[5000000]; 9 int head[N],m,n,x,y,ans,dis[N],T,tot=1,cnt,mp[4][110][110],a,num[110][110]; 10 inline void ins(int u,int v,int w) { 11 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w; 12 } 13 inline void insert(int u,int v,int w) { 14 ins(u,v,w); ins(v,u,0); 15 } 16 inline bool bfs(){ 17 memset(dis,-1,sizeof(dis)); queue<int>q; q.push(0); dis[0]=0; 18 while(!q.empty()) { 19 int x=q.front(); q.pop(); 20 for(int k=head[x];k;k=e[k].next) 21 if(dis[e[k].to]<0 && e[k].w>0) { 22 dis[e[k].to]=dis[x]+1; q.push(e[k].to); 23 } 24 } 25 if(dis[T]>0) return 1;else return 0; 26 } 27 int find(int x,int low){ 28 if(x==T) return low; 29 int delta=low,now; 30 for(int k=head[x];k;k=e[k].next) 31 if(e[k].w>0 && dis[e[k].to]==dis[x]+1){ 32 now=find(e[k].to,min(e[k].w,delta)); 33 e[k].w-=now; e[k^1].w+=now; delta-=now; 34 if(!delta) return low; 35 } 36 dis[x]=-1; 37 return low-delta; 38 } 39 int main () { 40 scanf("%d%d",&n,&m); T=50001; 41 rep(i,1,n) rep(j,1,m) scanf("%d",&a),num[i][j]=++cnt,insert(0,num[i][j],a),ans+=a; 42 rep(i,1,n) rep(j,1,m) scanf("%d",&a),insert(num[i][j],T,a),ans+=a; 43 rep(i,1,n-1) rep(j,1,m) scanf("%d",&mp[0][i][j]); 44 rep(i,1,n-1) rep(j,1,m) scanf("%d",&mp[1][i][j]); 45 rep(i,1,n) rep(j,1,m-1) scanf("%d",&mp[2][i][j]); 46 rep(i,1,n) rep(j,1,m-1) scanf("%d",&mp[3][i][j]); 47 rep(i,1,n-1) rep(j,1,m) { 48 x=++cnt; y=++cnt; 49 ans+=mp[0][i][j]+mp[1][i][j]; 50 insert(x,num[i][j],inf); insert(x,num[i+1][j],inf); 51 insert(num[i][j],y,inf); insert(num[i+1][j],y,inf); 52 insert(0,x,mp[0][i][j]); insert(y,T,mp[1][i][j]); 53 } 54 rep(i,1,n) rep(j,1,m-1) { 55 x=++cnt; y=++cnt; 56 ans+=mp[2][i][j]+mp[3][i][j]; 57 insert(x,num[i][j],inf); insert(x,num[i][j+1],inf); 58 insert(num[i][j],y,inf); insert(num[i][j+1],y,inf); 59 insert(0,x,mp[2][i][j]); insert(y,T,mp[3][i][j]); 60 } 61 while(bfs()) ans-=find(0,inf); 62 printf("%d",ans); 63 }