[ZJOI2009]狼和羊的故事

link

十多年前的省选题,还是浙江的省选……沧海桑田啊……

很简单一道题,网络流建模的应用,话说好像有很多题都是这样,在一个奇怪的方格上有各种奇怪的条件,数据范围还贼小,然后简单建模后直接跑网络流,更重要的是它们还都是可可爱爱的紫题……

唯一令我疑惑的是为什么它的N要开到两倍。

#include<cstdio>
#include<cstring>
//#define zczc
using namespace std;
const int N=205;
const int M=N*N;
const int maxn=1e9;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline int min(int s1,int s2){
	return s1<s2?s1:s2;
}

int s,t,cnt,m,n,in,id[N][N];

struct edge{
	int t,v,next;
}e[M<<4];
int head[M],esum=1;
inline void adde(int fr,int to,int val){
	e[++esum]=(edge){to,val,head[fr]};head[fr]=esum;
}
inline void add(int fr,int to,int val){
    if(fr==0||to==0||fr>cnt||to>cnt)return;
	adde(fr,to,val);adde(to,fr,0);
}
int f[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

int d[M],q[M],l,r;
bool check(int wh){
	memset(d,0,sizeof(d));
	d[q[l=r]=s]=1;
	while(l<=r)
		for(int i=head[wh=q[l++]],th;i;i=e[i].next)
			if(e[i].v&&d[th=e[i].t]==0)d[th]=d[wh]+1,q[++r]=th;
	return d[t];
}
int dinic(int wh,int val){
	if(wh==t)return val;
	int cost=0;
	for(int i=head[wh],th;i;i=e[i].next){
		if(e[i].v==0||d[th=e[i].t]!=d[wh]+1)continue;
		int now=dinic(th,min(val,e[i].v));
		val-=now,cost+=now,e[i].v-=now,e[i^1].v+=now;
	}
	return d[wh]=val?0:d[wh],cost;
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);
	s=++cnt;t=++cnt;
	for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)id[i][j]=++cnt;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			read(in);
			if(in==1)add(s,id[i][j],maxn);
			if(in==2)add(id[i][j],t,maxn);
			for(int k=0;k<4;k++)add(id[i][j],id[i+f[k][0]][j+f[k][1]],1);
		}
	}
	int ans=0;
	while(check(0))ans+=dinic(s,maxn);
	printf("%d\n",ans);
	
	return 0;
}
posted @ 2022-03-12 16:27  Feyn618  阅读(15)  评论(0编辑  收藏  举报