[USACO5.4]Telecowmunication-最小割

题目

题目
题目大意:

给定一张无向图图上两点,求最少割掉几个点,这两点不连通

代码

最小割,注意把点转成边。

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;
const int inf=1<<30,N=640,M=4440;	//稍微开大点
int to[M],val[M],nxt[M],head[N],cnt;
int n,m,s,t,maxflow,incf[N],pre[N];
bool v[N]; 

void add(int u,int v,int w) {
	to[++cnt]=v;
	val[cnt]=w;
	nxt[cnt]=head[u];
	head[u]=cnt;
}

bool ek() { //最大流=最小割
	memset(v,0,sizeof(v));
	v[s]=true;
	incf[s]=inf;
	queue<int> q;
	q.push(s);
	while(!q.empty()) {
		int x=q.front();
		q.pop();
		for(int i=head[x];i;i=nxt[i]) {
			int y=to[i];
			if(val[i]>0 and !v[y]) {
				v[y]=true;
				pre[y]=i;
				incf[y]=min(val[i],incf[x]);
				q.push(y);
				if(y==t)
				  return true;
			}
		}
	}
	return false;
}

void update() {
	int x=t;
	while(x!=s) {
		int i=pre[x];
		val[i]-=incf[t];
		val[i^1]+=incf[t];
		x=to[i^1];
	}
	maxflow+=incf[t];
}

int main() {
	cnt=1;
	cin>>n>>m>>s>>t;
	for(int i=1;i<=n;i++) { 
		add(i,i+n,1);
		add(i+n,i,0);
	} 
	s+=n;
	while(m--) {
		int u,v;
		cin>>u>>v;
		add(u,v+n,0);   //点边转化
		add(v+n,u,inf);
		add(v,u+n,0);
		add(u+n,v,inf);
	}
	while(ek())
	  update();
	cout<<maxflow;
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/wyc06/p/12643928.html