ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2598 [ZJOI2009]狼和羊的故事

2020-06-12 20:59:21  阅读:228  来源: 互联网

标签:ch yl 故事 get int add rg ZJOI2009 P2598


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

一眼就可以看出来,要用最小割把狼和羊分开,那 \(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;
}

标签:ch,yl,故事,get,int,add,rg,ZJOI2009,P2598
来源: https://www.cnblogs.com/XiaoVsun/p/13110235.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有