BZOJ3894 文理分科

传送门

神仙建模。(想不出想不出)好早之前听的一道题了,完全没有印象了QAQ

就是最小割模型肯定比较好看出来

然后呢对于处理一个人周围的都选的一样的话,那么就应该是新建一个全文/理点,这几个人连inf,然后收益连源汇就可以。

(网络流要多大胆建点!)

查了好久发现cnt没赋1【猛虎落泪】

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define inf 20021225
#define N 110
#define mxn 40010
using namespace std;

int art[N][N],sci[N][N],sa[N][N],ss[N][N];
struct edge{int to,lt,f;}e[mxn*20];
int in[mxn],n,m,cnt=1,dis[mxn],s,t;
void add(int x,int y,int f)
{
	e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].f=f;in[x]=cnt;
	e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].f=0;in[y]=cnt;
}
queue<int> que;
bool bfs()
{
	while(!que.empty())	que.pop();
	memset(dis,0,sizeof(dis));
	dis[s]=1;que.push(s);
	while(!que.empty())
	{
		int x=que.front();que.pop();
		for(int i=in[x];i;i=e[i].lt)
		{
			int y=e[i].to;
			if(dis[y]||!e[i].f)	continue;
			dis[y]=dis[x]+1;
			if(y==t)	return true;
			que.push(y);
		}
	}
	return false;
}

int dfs(int x,int flow)
{
	if(x==t||!flow)	return flow;
	int cur=flow;
	for(int i=in[x];i;i=e[i].lt)
	{
		int y=e[i].to;
		if(dis[y]==dis[x]+1&&e[i].f)
		{
			int tmp=dfs(y,min(cur,e[i].f));
			e[i].f-=tmp;e[i^1].f+=tmp;cur-=tmp;
			if(!cur)	return flow;
		}
	}
	dis[x]=-1;
	return flow-cur;
}

int dinic()
{
	int ans=0;
	while(bfs())	ans+=dfs(s,inf);
	return ans;
}

int id(int x,int y,int dep)
{
	return dep*n*m+m*(x-1)+y;
}
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
int main()
{
	int x,y,i;
	scanf("%d%d",&n,&m);
	s=n*m*3+1;t=s+1;
	int ans=0;
	// s art t sci
	for(x=1;x<=n;x++)
		for(y=1;y<=m;y++)
		{
			scanf("%d",&art[x][y]);
			ans+=art[x][y];
			add(s,id(x,y,0),art[x][y]);
		}
	for(x=1;x<=n;x++)
		for(y=1;y<=m;y++)
		{
			scanf("%d",&sci[x][y]);
			ans+=sci[x][y];
			add(id(x,y,0),t,sci[x][y]);
		}
	for(x=1;x<=n;x++)
		for(y=1;y<=m;y++)
		{
			scanf("%d",&sa[x][y]);
			ans+=sa[x][y];
			add(s,id(x,y,1),sa[x][y]);
			add(id(x,y,1),id(x,y,0),inf);
			for(i=0;i<4;i++)
			{
				int tx=x+xx[i],ty=y+yy[i];
				if(tx<=0||ty<=0||tx>n||ty>m)	continue;
				add(id(x,y,1),id(tx,ty,0),inf);
			}
		}
	for(x=1;x<=n;x++)
		for(y=1;y<=m;y++)
		{
			scanf("%d",&ss[x][y]);
			ans+=ss[x][y];
			add(id(x,y,2),t,ss[x][y]);
			add(id(x,y,0),id(x,y,2),inf);
			for(i=0;i<4;i++)
			{
				int tx=x+xx[i],ty=y+yy[i];
				if(tx<=0||ty<=0||tx>n||ty>m)	continue;
				add(id(tx,ty,0),id(x,y,2),inf);
			}
		}
	ans-=dinic();
	printf("%d\n",ans);
	return 0;
}

 

posted @ 2018-12-08 17:17  寒雨微凝  阅读(96)  评论(0编辑  收藏  举报