[luogu2774][网络流24题]方格取数

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88695401

luogu2774

这题可以发现我们把格子染色,使得相邻的格子的颜色不同,然后把白色格子和s连一条边,黑色格子和t连一条边,就转化为了最小割问题

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=1000005,M=1000005;
const int inf=0x3f3f3f3f;
int a[105][105];
namespace Dinic{
	int vis[M<<1],head[M<<1],nxt[M<<1],e[M<<1],tot=1;
	inline void add(int x,int y,int z){
		vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;e[tot]=z;
		vis[++tot]=x;nxt[tot]=head[y];head[y]=tot;e[tot]=0;
	}
	int s,t,d[N];
	queue<int>q;
	inline bool spfa(){
		memset(d,0,sizeof(d));
		while(!q.empty()) q.pop();
		q.push(s);d[s]=1;
		while(!q.empty()){
			int x=q.front();q.pop();
			for(int i=head[x];i;i=nxt[i]){
				int y=vis[i];
				if(!d[y] && e[i]){
					q.push(y);
					d[y]=d[x]+1;
					if(y==t) return 1;
				}
			}
		}
		return 0;
	}
	int dinic(int x,int flow){
		if(x==t) return flow;
		int rest=flow,k;
		for(int i=head[x];i && rest;i=nxt[i])
			if(e[i] && d[vis[i]]==d[x]+1){
				k=dinic(vis[i],min(e[i],rest));
				if(!k) d[vis[i]]=0;
				e[i]-=k;e[i^1]+=k;
				rest-=k;
			}
		return flow-rest;
	}
	inline int maxflow(){
		int flow=0,maxflow=0;
		while(spfa())
			while(flow=dinic(s,inf)) maxflow+=flow;
		return maxflow;
	}
}
using namespace Dinic;
int n,m;
int main(){
	n=read();m=read();s=0,t=n*m+1;int cnt=0,sum=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			++cnt;
			a[i][j]=read();sum+=a[i][j];
			if((i+j)%2){
				add(s,cnt,a[i][j]);
				if(j<m) add(cnt,cnt+1,inf);
				if(j>1) add(cnt,cnt-1,inf);
				if(i<n) add(cnt,cnt+m,inf);
				if(i>1) add(cnt,cnt-m,inf);
			}
			else add(cnt,t,a[i][j]);
		}
	cout<<sum-maxflow();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/88695401