UVA - 10480 Sabotage 输出最小割方案

题目链接

https://vjudge.net/problem/UVA-10480

题意

无向图求最小割的方案

思路

最小割部分是模版,问题在于最小割的方案如何输出。

首先根据最小割最大流定理,我们跑一遍Dinic就可以求出最小割,这时残量网络中s和t已经不再联通了。我们可以从s开始跑一遍dfs,沿着所有还未满流的边搜索,所有能到达的节点就是和s在同一集合的节点。之后我们遍历每一条边,将边起点终点不在同一集合内的输出即可。

注意需要修改下链式前向星,每一个edge结构体内存一下起点。

附一篇最小割相关拓展的优质博客:https://www.cnblogs.com/lyttt/p/11817977.html

代码

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib> 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
using namespace std;
	typedef long long ll;
	const int inf=0x3f3f3f3f;
	const int maxn=1010;
	const int maxe=1010;

	int head[maxn],cnt;
	struct Edge{
    
    
		int u;
		int v;
		int w;
		int next;
	}edge[maxe];

	int n,m,s,t;
	ll maxflow;
	int deep[maxn];
	int now[maxe];
	bool s_or_t[maxn];//0代表和t相连,1是和s相连 

	void init(){
    
    
		memset(head,-1,sizeof(head));
		memset(s_or_t,0,sizeof s_or_t);
		cnt=0;
		maxflow=0; 
		return ;	
	}
	void add(int u,int v,int w){
    
    
	//	cout<<u<<" "<<v<<" "<<w<<endl;
		edge[cnt].u=u;
  		edge[cnt].v=v;
		edge[cnt].w=w;
		edge[cnt].next=head[u];
		head[u]=cnt++;
	}

	inline bool bfs(){
    
    
    	memset(deep,0x3f,sizeof(deep));
    	queue<int>q;
    	q.push(s);deep[s] = 0;now[s] = head[s];
    	while(q.size()){
    
    
        	int x = q.front();q.pop();
        	for(int i=head[x];i!=-1;i=edge[i].next){
    
    
        	    int y=edge[i].v;
         	    if(edge[i].w>0&&deep[y]==inf){
    
    
         	    	q.push(y);
        	        now[y]=head[y];
         	       	deep[y]=deep[x]+1;
        	        if(y==t)	return 1;
				}
        	}
    	}
    	return 0;
	}


	ll dfs(int x,int flow){
    
    
    	if(x==t)	return flow;
    	ll ans = 0,k,i;
    	for(i=now[x];i!=-1&&flow;i=edge[i].next){
    
    
        	now[x]=i;
        	int y=edge[i].v;
        	if(edge[i].w>0&&(deep[y]==deep[x]+1)){
    
    
        	    k=dfs(y,min(flow,edge[i].w));
         		if(!k)	deep[y]=inf;
            	edge[i].w-=k;
            	edge[i^1].w+=k;
            	ans+=k;
            	flow-=k;
        	}
    	}
    	return ans;
	}	

	void dinic(){
    
    
    	while(bfs())
    	    maxflow+=dfs(s,inf);
	}
	//在残量网络中跑dfs 
	void output_dfs(int u){
    
    
		if(s_or_t[u])
			return ;
		else{
    
    
			s_or_t[u]=1;
		} 
		for(int i=head[u];~i;i=edge[i].next)
			if(edge[i].w>0)//只能通过还有余量的边 
				output_dfs(edge[i].v);
	}
	int main(){
    
    	
		IOS
		while(cin>>n>>m){
    
    
			if(!n&&!m)
				break;
			init();
			while(m--){
    
    
				int u,v,w;
				cin>>u>>v>>w;
				add(u,v,w);
				add(v,u,w);
			} 
			s=1,t=2;
			dinic();
			output_dfs(s);
			for(int i=0;i<cnt;i+=2){
    
    
				int u=edge[i].u,v=edge[i].v;
				if(s_or_t[u]!=s_or_t[v])
					cout<<u<<" "<<v<<endl;
			}
	 		cout<<endl;
		}
    	return 0;
	}

猜你喜欢

转载自blog.csdn.net/TheSunspot/article/details/108348352