Usaco Training Section 5.4 Telecowmunication

一道最小割点集的题目。因为本人比较菜,一开始没想到拆点,没做出来。后来看了题解,才知道拆点做挺方便的

Usaco Training Section 5.4 Telecowmunication

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 1<<29
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
#define r1 rt<<1
#define r2 rt<<1|1
#define ld long double
using namespace std;

inline int read(){
	int x=0;char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

const int M=1005;
int d[M],n,m,s,t,arc[M][M],tmp[M][M];

inline bool bfs(){
	memset(d,0,sizeof(d));
	queue<int> q;
	q.push(s);d[s]=1;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int v=1;v<=n;++v){
			if(arc[u][v]&&!d[v]){
				d[v]=d[u]+1;
				if(d[t]!=0) return 1;
				q.push(v);
			}
		}
	}
	return 0;
}

inline int dfs(int u,int flow){
	if(u==t) return flow;
	for(int v=1;v<=n;++v){
		if(arc[u][v]&&d[v]==d[u]+1){
			int k=dfs(v,min(flow,arc[u][v]));
			if(k<=0) continue;
			arc[u][v]-=k;
			arc[v][u]+=k;
			return k;
		}
	}
	return 0;
}

inline int dinic(){
	int ans=0;
	while(bfs()){
		while(int di=dfs(s,inf)) ans+=di;
	}
	return ans;
}

int main()
{
	freopen("telecow.in","r",stdin);
	freopen("telecow.out","w",stdout);
	n=read(),m=read(),s=read(),t=read();
	s*=2;t=t*2-1;
	memset(arc,0,sizeof(arc));
	memset(tmp,0,sizeof(tmp));
	for(int i=1;i<=n;++i){
		arc[i*2-1][i*2]=1;
		tmp[i*2-1][i*2]=1;
	}
	n*=2;
	for(int i=1;i<=m;++i){
		int u=read(),v=read();
		arc[u*2][v*2-1]=arc[v*2][u*2-1]=inf;
		tmp[u*2][v*2-1]=tmp[v*2][u*2-1]=inf;
	}
	int ans=dinic();
	printf("%d\n",ans);
	if(!ans){
		puts("0");
		return 0;
	}
	bool f=0;
    for(int i=1;i<=n;i+=2){
    	if(i==s-1||i==t) continue;
    	for(int j=1;j<=n;++j)
    		for(int k=1;k<=n;++k)
    			arc[j][k]=tmp[j][k];
    	arc[i][i+1]=0;
    	if(dinic()==ans-1){
    		--ans;
    		if(f) printf(" ");
    		else f=1;
    		printf("%d",(i+1)/2);
    		tmp[i][i+1]=0;
    	}
    }
    puts("");
    return 0;
}