luogu P4313 文理分科 网络流最小割模型

https://www.luogu.com.cn/blog/CJL/solution-p4313

#include<iostream>
#include<cstring>
using namespace std;
const int N=400020;
#define int long long
const int INF=1e9;
int n,m,S,T;
int h[N],e[N],ne[N],idx,w[N];
int q[N],d[N],cur[N];
void add(int a,int b,int c)
{
	e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
	e[idx]=a,w[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs()
{
	int hh=0;
	int tt=0;
	memset(d,-1,sizeof d);
	q[0]=S;
	d[S]=0;
	cur[S]=h[S];
	while(hh<=tt)
	{
		int t=q[hh++];
		for(int i=h[t]; i!=-1; i=ne[i])
		{
			int ver=e[i];
			if(d[ver]==-1&&w[i])
			{
				d[ver]=d[t]+1;
				cur[ver]=h[ver];
				if(ver==T)
					return true;
				q[++tt]=ver;
			}
		}
	}
	return false;
}
int find(int u,int limit)
{
	if(u==T)
		return limit;
	int flow=0;
	for(int i=cur[u]; ~i&&flow<limit; i=ne[i])
	{
		cur[u]=i;
		int ver=e[i];
		if(d[ver]==d[u]+1&&w[i])
		{
			int t=find(ver,min(w[i],limit-flow));
			if(!t)
				d[ver]=-1;
			w[i]-=t;
			w[i^1]+=t;
			flow+=t;
		}
	}
	return flow;
}
int dinic()
{
	int r=0;
	int flow;
	while(bfs())
		while(flow=find(S,INF))
			r+=flow;
	return r;
}
int get(int i,int j)
{
	return (i-1)*m+j;
}
bool check(int x,int y)
{
	return x>=1&&x<=n&&y>=1&&y<=m;
}
signed main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m;
	int tot=n*m;
	S=0,T=++tot;
	int sum=0;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			int x;
			cin>>x;
			sum+=x;
			add(S,get(i,j),x);
		}

	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			int x;
			cin>>x;
			sum+=x;
			add(get(i,j),T,x);
		}

	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			int x;
			cin>>x;
			sum+=x;
			add(S,++tot,x);
			add(tot,get(i,j),INF);
			if(check(i-1,j))
				add(tot,get(i-1,j),INF);
			if(check(i,j-1))
				add(tot,get(i,j-1),INF);
			if(check(i+1,j))
				add(tot,get(i+1,j),INF);
			if(check(i,j+1))
				add(tot,get(i,j+1),INF);
		}

	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
		{
			int x;
			cin>>x;
			sum+=x;
			add(++tot,T,x);
			add(get(i,j),tot,INF);
			if(check(i-1,j))
				add(get(i-1,j),tot,INF);
			if(check(i+1,j))
				add(get(i+1,j),tot,INF);
			if(check(i,j+1))
				add(get(i,j+1),tot,INF);
			if(check(i,j-1))
				add(get(i,j-1),tot,INF);
		}
	cout<<sum-dinic()<<endl;
}
posted @ 2020-10-27 21:41  晴屿  阅读(105)  评论(0编辑  收藏  举报