题目要求 任意两个点不连通 这句话怎么有点熟悉?
然后联想到最小割的定义:一个边集被删除以后S,T不再联通,则称该边集为网络的割。边的容量之和最小的割成为网络的最小割。
emmm S,T 不再联通 确实有点像
于是这道题就可以用网络流最大流来做!
将一个点\(x\) 拆成 \(x\)\(x+n\) 在这之间连有向边流量为1
对于原图中的无向边\((x,y)\),在网络中连接有向边\((x',y),(y',x)\),流量为inf
这样我们就可以从原图点的集合中 枚举任意两个点作为S,T 然后跑网络流最大流即可 注意源点和汇点 他们的出点和入点的流量为inf 即\((s,s+n),(t,t+n)\) 这两条边的流量为inf
细节详见代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=1000;
const int inf=1e9;
int fir[maxn<<1],nxt[maxn<<1],to[maxn<<1],val[maxn<<1],mf,ans;
int n,m,t,a[maxn],b[maxn],S,T,tot=1,dep[maxn],cnt[maxn],flag;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}
void add(int x,int y,int z){
	nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;val[tot]=z;
	nxt[++tot]=fir[y];fir[y]=tot;to[tot]=x;val[tot]=0;
}
void build_map(){
	memset(fir,0,sizeof(fir));tot=1;
	for(int i=1;i<=n;i++){
		if(i==S || i==T) add(i,i+n,inf);
		else add(i,i+n,1);	
	}
	for(int i=1;i<=m;i++)
		add(a[i]+n,b[i],inf),add(b[i]+n,a[i],inf);
}
void bfs(){
	memset(cnt,0,sizeof(cnt));
	memset(dep,0xff,sizeof(dep));
	queue<int> q;
	q.push(T);dep[T]=0;cnt[dep[T]]++;
	while(!q.empty()){
		int x=q.front();q.pop();
		for(int i=fir[x];i;i=nxt[i]){
			int y=to[i];
			if(dep[y]==-1){
				dep[y]=dep[x]+1;
				cnt[dep[y]]++;
				q.push(y);
			}
		}
	}
}
int dfs(int x,int flow){
	if(x==T){
		mf+=flow;return flow;
	}
	int f=0;
	for(int i=fir[x];i;i=nxt[i]){
		int y=to[i];
		if(dep[y]==dep[x]-1 && val[i]){
			int ff=dfs(y,min(flow-f,val[i]));
			if(ff){
				f+=ff;val[i]-=ff;val[i^1]+=ff;
			}
			if(f==flow)	return f;
		}
	}
	if(!--cnt[dep[x]])	flag=1;
	cnt[++dep[x]]++;
	return f;
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d %d",&n,&m);ans=inf;
		for(int i=1,x,y;i<=m;i++)
			a[i]=read()+1,b[i]=read()+1;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i==j) continue;
				S=i;T=j;mf=0;
				build_map();
				bfs();flag=0;
				while(!flag)
					dfs(S,inf);
				ans=min(ans,mf);
			}
		}
		if(n<=1 || ans==inf) printf("%d\n",n);
		else printf("%d\n",ans);
	}
}
posted on 2019-10-25 22:00  萌德真帅  阅读(206)  评论(0编辑  收藏  举报