P2598 [ZJOI2009]狼和羊的故事

既可以是一眼题又可以是有些东西的题

一眼就可以看出来,要用最小割把狼和羊分开,那 \(S\) 向狼连 \(inf\),羊向 \(T\)\(inf\),每个点向周围连 1,考虑割掉的边是栅栏

之所以说它有些东西,是应为它可以表示成数学形式,考虑将狼划分成 0 集合,将羊划分成 1 集合,没有归属的点随便

如果两个点不在同一个集合,那么它需要栅栏分开,就是每个点向周围连 1 的边,由此可知,0 的归属就不需要讨论了

#include<bits/stdc++.h>
using namespace std;
#define rg register
inline int read(){
	rg char ch=getchar();
	rg int x=0,f=0;
	while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}
int head[100010],ver[200010],flow[200010],nxt[200010],tot=1,hh[100010];
int mp[110][110];
int dis[100010],ans;
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int n,m,s,t;
inline void add(int x,int y,int f){
	ver[++tot]=y;
	flow[tot]=f;
	nxt[tot]=head[x];
	head[x]=tot;
}
inline int get(int i,int j){
	return (i-1)*m+j;
}
int bfs(){
	queue<int> q;
	q.push(s);
	for(int i=s;i<=t;++i) hh[i]=head[i];
	memset(dis,0,sizeof dis);
	dis[s]=1;
	while(!q.empty()){
		int x=q.front();q.pop();
		for(int y,i=head[x];i;i=nxt[i]){
			y=ver[i];
			if(!dis[y]&&flow[i]){
				dis[y]=dis[x]+1;
				q.push(y);
			}
		}
	}
	return dis[t]?true:false;
}
int dfs(int x,int f){
	if(x==t||!f) return f;
	int used=0;
	for(int y,w,&i=hh[x];i;i=nxt[i]){
		y=ver[i];
		if(dis[y]==dis[x]+1&&flow[i]){
			w=dfs(y,min(f-used,flow[i]));
			if(w){
				flow[i]-=w;
				flow[i^1]+=w;
				used+=w;
				if(used==f) return f;
			}
		}
	}
	if(!used) dis[x]=0;
	return used;
}
void dinic(){
	while(bfs()) ans+=dfs(s,99999999);
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			mp[i][j]=read();
	s=0,t=n*m+1;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			if(mp[i][j]!=1){
				for(int k=0;k<4;++k){
					int xl=j+dx[k],yl=i+dy[k];
					if(xl<1||yl<1||xl>m||yl>n) continue;
					add(get(i,j),get(yl,xl),1);
					add(get(yl,xl),get(i,j),0);
				}
				if(mp[i][j]==2){
					add(s,get(i,j),99999999);
					add(get(i,j),s,0);
				}
			}else{
				add(get(i,j),t,99999999);
				add(t,get(i,j),0);
			}
		}
	}
	dinic();
	cout<<ans<<endl;
	return 0;
}
posted @ 2020-06-12 20:45  __int256  阅读(152)  评论(0编辑  收藏  举报