【[ZJOI2009]狼和羊的故事】最大流最小割

由于看完最大流就跟着做到了最小割的题。。。一道题愣是看了一个多小时没有思路,看标签才发现我还有知识欠缺---》最小割走起!

洛谷传送门:https://www.luogu.org/problemnew/show/P2598

/*由于本蒟蒻刚刚学最小割,这里就不单纯写本题题解,同时放出三个定理来(from root's jiangyi)

定理一:如果f是网络中的一个流,CUT(S,T)是任意一个割,那么f的值等于正向割边的流量与负向割边的流量之差。(最大流流量不超过任何割容量)

定理2:在任何网络中,如果f是一个流,CUT(S,T)是一个割,且f的值等于割CUT(S,T)的容量,那么f是一个最大流,CUT(S,T)是一个最小割(容量最小的割)。

定理3:最大流最小割定理:在任何的网络中,最大流的值等于最小割的容量。

*/

其实这是一道UVA1515的简化版,luogu传送门https://www.luogu.org/problemnew/show/UVA1515

翻译在这道题讨论区里面,原版本里面除了划分以外还有修改地盘操作,但稍加思索也并不难,看向本题。

这道题很显然的一道最大流最小割板子题。我们最后就是求将羊和狼割成两块的最小割,直接S连所有的羊,狼连所有的T,容量为inf,然后将羊与狼连接,容量为1就好啦!

值得斟酌的是里面的0.稍加思索之后,我们把0当做羊来连边,因为我们看羊的连边即是连向0和狼,而0的连边也是连向0和狼,但0不与S相连,容量这里都为1。

大致最后的图是 :   S-》羊-》0-》狼-》T

搞定!

//S->yang-0-> lang ->T	 
#include<bits/stdc++.h>
#define id(x,y) ((x-1)*m+y)
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,S,T;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
int tu[105][105];
int la[10005],nt[100005],en[100005],v[100005],owo=1;
void addedge(int a,int b,int c)
{
	en[++owo]=b; nt[owo]=la[a]; la[a]=owo; v[owo]=c;
}
int dis[10005],cnt[10005];
int sap(int x,int flow)
{
	if(x==T) return flow;
	int dlt=0,tmp;
	for(int it=la[x];it;it=nt[it])
	{
		if(v[it]&&dis[x]==dis[en[it]]+1)
		{
			tmp=sap(en[it],min(flow-dlt,v[it]));
			dlt+=tmp;
			v[it]-=tmp;
			v[it^1]+=tmp;
			if(dlt==flow||dis[S]>=n*m+2) return dlt;
		}
	}
	if(dis[S]>=n*m+2) return dlt;
	cnt[dis[x]]--;
	if(!cnt[dis[x]]) dis[S]=n*m+2;
	dis[x]++;
	cnt[dis[x]]++;
	return dlt;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",&tu[i][j]);
	S=n*m+1; T=n*m+2;
	int nx,ny;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(tu[i][j]==2)
			{
				addedge( id(i,j) ,T, 0x3f3f3f3f );
				addedge( T,id(i,j), 0);
			}
			else 
			{
				if(tu[i][j]==1)
				{
				addedge( S,id(i,j) ,0x3f3f3f3f );
				addedge( id(i,j),S,0);
				} 
				for(int k=0;k<4;k++)
				{
					nx=i+dx[k]; ny=j+dy[k];
					if(nx>=1&&nx<=n&&ny>=1&&ny<=m) 
					{
						if(tu[nx][ny]==0||tu[nx][ny]==2)
						{
							addedge(id(i,j),id(nx,ny),1);
							addedge( id(nx,ny),id(i,j),0 );
						}
					}
				}
			}
		}
	int ans=0;
	while(dis[S]<n*m+2)
	{
		ans+=sap(S,0x3f3f3f3f);
	}
	printf("%d",ans);
}

 

 

 

posted @ 2018-04-14 22:10  Newuser233  阅读(8)  评论(0)    收藏  举报