[Network Flow 24 Questions] Minimum Cut of P2744 Lattice Number Problem

Posted by Transwarp-Tim on Fri, 04 Oct 2019 16:31:34 +0200

In this paper, we give a square of M * nm * n m n * n. Each square has a weight. We select several squares and make the sum of weights maximum, but no two squares can be adjacent to each other, so that the maximum weight can be obtained.
Not too complicated Minimum Cut Model problem, but I am not familiar with this type at present.
Try to divide the square into two parts. This one can be dyed in black and white. The two colors will not be adjacent to each other. Then for the Hague, the flow of the weights of each lattice connected by the source point, and for the white lattice, the flow of the weights of each lattice connected by the confluence point. For black and white, as long as the adjacent lattices are connected, the flow is infinite, because the adjacent relationship is fixed.
Then run the smallest cut. The answer is to subtract the smallest cut from all the choices.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e2+7;
int a[N][N]; 
int mp[N][N]; 
namespace Dinic {
	const int N=1e3+3,M=1e4+3; 
	int front[N],head[N],dep[N],tot=-1,n,S,T;
	struct edge{ int v,nxt;ll w; }e[2*M];
	void init() {
		tot=-1;
		for(int i=1;i<=n;i++) front[i]=-1;
	}
	void add(int u,int v,ll w) {
		e[++tot].v=v,e[tot].w=w,e[tot].nxt=front[u],front[u]=tot;
		e[++tot].v=u,e[tot].w=0,e[tot].nxt=front[v],front[v]=tot;
	}
	bool bfs() {
		for(int i=1;i<=n;i++) dep[i]=0;
		queue<int> q;
		q.push(S);
		dep[S]=1;
		while(!q.empty()) {
			int u=q.front();
			q.pop();
			for(int i=front[u];i!=-1;i=e[i].nxt) {
				int v=e[i].v;
				if(dep[v]==0&&e[i].w) {
					dep[v]=dep[u]+1;
					q.push(v); 
				}
			}
		}
		return dep[T];
	}
	ll dfs(int cur,ll dis=1e18) {
		if(cur==T) return dis;
		ll flow=0,sum=0;
		for(int &i=head[cur];i!=-1;i=e[i].nxt) {
			int v=e[i].v;
			if(dep[v]==dep[cur]+1&&e[i].w) {
				flow=dfs(v,min(dis,e[i].w));
				dis-=flow,sum+=flow;
				e[i].w-=flow,e[i^1].w+=flow;
				if(!dis) break;
			}
		}
		return sum;
	}
	ll solve() {
		ll ans=0;
		while(bfs()) {
			for(int i=1;i<=n;i++) head[i]=front[i];
			ans+=dfs(S);
		}
		return ans;
	}
}
int m,n;  
bool check(int x,int y) {
	if(x>=1&&x<=m&&y>=1&&y<=n) return 1;
	else return 0;
}
int main() {
	scanf("%d%d",&m,&n);
	int tot=0;
	int S=n*m+1;
	int T=n*m+2;
	Dinic::S=S;
	Dinic::T=T;
	Dinic::n=n*m+2;
	Dinic::init();
	for(int i=1;i<=m;i++) {
		for(int j=1;j<=n;j++) {
			scanf("%d",&a[i][j]);
			mp[i][j]=++tot;
			if((i+j)%2==0) Dinic::add(S,tot,a[i][j]);
			else Dinic::add(tot,T,a[i][j]);
		}
	}
	for(int i=1;i<=m;i++) {
		for(int j=1;j<=n;j++) {
			if((i+j)%2==0) {
				if(check(i-1,j)) Dinic::add(mp[i][j],mp[i-1][j],1e9); 
				if(check(i,j-1)) Dinic::add(mp[i][j],mp[i][j-1],1e9);
				if(check(i+1,j)) Dinic::add(mp[i][j],mp[i+1][j],1e9);
				if(check(i,j+1)) Dinic::add(mp[i][j],mp[i][j+1],1e9);
			} 
		}
	}
	ll sum=0;
	for(int i=1;i<=m;i++) {
		for(int j=1;j<=n;j++) {
			sum+=a[i][j];
		}
	} 
	printf("%lld\n",sum-Dinic::solve());
	return 0;
}