bzoj2127: happiness

最小割。加点然后sm-maxflow就好了。做过类型题

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
	int x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x;
} 
const int nmax=6e4+5;
const int maxn=4e5+5;
const int inf=0x7f7f7f7f;
struct edge{
	int to,cap;edge *next,*rev;
};
edge es[maxn],*pt=es,*head[nmax];
void add(int u,int v,int d){
	pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
	pt->to=u;pt->cap=0;pt->next=head[v];head[v]=pt++;
	head[u]->rev=head[v];head[v]->rev=head[u];
}
edge *p[nmax],*cur[nmax];
int h[nmax],cnt[nmax],id[105][105];
int maxflow(int s,int t,int n){
	cnt[0]=n;int x=s,flow=0,a=inf;edge *e;
	while(h[s]<n){
		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[e->to]+1==h[x]) break;
		if(e){
			a=min(a,e->cap);cur[x]=p[e->to]=e;x=e->to;
			if(x==t){
				while(x!=s) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to;
				flow+=a,a=inf;
			}
		}else{
			if(!--cnt[h[x]]) break;
			h[x]=n;
			for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) h[x]=h[e->to]+1,cur[x]=e;
			cnt[h[x]]++;
			if(x!=s) x=p[x]->rev->to;
		}
	}
	return flow;
}
int main(){
	int n=read(),m=read(),s=0,t=1,cnt=1,tmp,sm=0;
	rep(i,1,n) rep(j,1,m) id[i][j]=++cnt;
	rep(i,1,n) rep(j,1,m) add(s,id[i][j],tmp=read()),sm+=tmp;
	rep(i,1,n) rep(j,1,m) add(id[i][j],t,tmp=read()),sm+=tmp;
	rep(i,1,n-1) rep(j,1,m) add(s,++cnt,tmp=read()),add(cnt,id[i][j],inf),add(cnt,id[i+1][j],inf),sm+=tmp;
	rep(i,1,n-1) rep(j,1,m) add(++cnt,t,tmp=read()),add(id[i][j],cnt,inf),add(id[i+1][j],cnt,inf),sm+=tmp;
	rep(i,1,n) rep(j,1,m-1) add(s,++cnt,tmp=read()),add(cnt,id[i][j],inf),add(cnt,id[i][j+1],inf),sm+=tmp;
	rep(i,1,n) rep(j,1,m-1) add(++cnt,t,tmp=read()),add(id[i][j],cnt,inf),add(id[i][j+1],cnt,inf),sm+=tmp;
	printf("%d
",sm-maxflow(s,t,cnt+1));
	return 0;
}
/*
1 2
1 1
100 110
1
1000 
*/

  

2127: happiness

Time Limit: 51 Sec  Memory Limit: 259 MB
Submit: 1681  Solved: 820
[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

Sample Output

1210
【样例说明】
两人都选理,则获得100+110+1000的喜悦值。
【数据规模】
对于100%以内的数据,n,m<=100 所有喜悦值均为小于等于5000的非负整数

HINT

 

Source

原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5927261.html