SW算法求全局最小割

//O(n^3)实现
#include <bits/stdc++.h>

using namespace std;

#define sfi(a) scanf("%d",&a)
#define sfd(a) scanf("%lf",&a)
#define sfl(a) scanf("%lld",&a)
#define sfs(a) scanf("%s",a)

#define rep(i,a,b) for(int i=int(a);i<int(b);++i)
#define dwn(i,b,a) for(int i=int(b-1);i>=int(a);--i)

#define mem(a,p) memset(a,p,sizeof(a))

typedef long long LL;
typedef unsigned UINT;
typedef unsigned long long ULL;

#define MAXN 305

const LL INF=1e16;

struct Stoer_Wagner
{
	LL e[MAXN][MAXN];
	
	int n;
	
	LL w[MAXN];
	bool vis[MAXN],bin[MAXN];
	
	void init(int nn)
	{
		n=nn;
		mem(e,0);
	}
	
	void AddEdge(int u,int v,int w)
	{
		e[u][v]+=w;
		e[v][u]+=w;
	}
	
	LL Search(int &s,int &t)
	{
		mem(vis,0);
		mem(w,0);
		
		t=1;
		while(bin[t])t++;
		vis[t]=true;
		
		while(true)
		{
			rep(i,1,n+1)
			{
				if(vis[i]||bin[i])continue;
				w[i]+=e[t][i];
			}
			int p=-1;
			rep(i,1,n+1)
			{
				if(vis[i]||bin[i])continue;
				if(p==-1||w[i]>w[p])p=i;
			}
			if(p==-1)break;
			s=t;
			t=p;
			vis[t]=true;
		}
		
		return w[t];
	}
	
	LL Solve()
	{
		mem(bin,0);
		LL ret=INF;
		int s,t;
		rep(i,0,n-1)
		{
			LL pans=Search(s,t);
			ret=min(ret,pans);
			bin[t]=true;
			rep(i,1,n+1)
			{
				if(bin[i])continue;
				if(i==s)continue;
				e[s][i]+=e[t][i];
				e[i][s]+=e[i][t];
			}
		}
		return ret;
	}
}S;

int main()
{
	int n,m,s;
	while(scanf("%d%d%d",&n,&m,&s)==3)
	{
		if(n==0)break;
		S.init(n);
		rep(i,0,m)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			S.AddEdge(u,v,w);
		}
		printf("%lld\n",S.Solve());
	}
	return 0;
}
//堆优化版本,O(nmlogm)实现
#include <bits/stdc++.h>

using namespace std;

#define sfi(a) scanf("%d",&a)
#define sfd(a) scanf("%lf",&a)
#define sfl(a) scanf("%lld",&a)
#define sfs(a) scanf("%s",a)

#define rep(i,a,b) for(int i=int(a);i<int(b);++i)
#define dwn(i,b,a) for(int i=int(b-1);i>=int(a);--i)

#define mem(a,p) memset(a,p,sizeof(a))

typedef long long LL;
typedef unsigned UINT;
typedef unsigned long long ULL;

#define MAXN 305

const LL INF=1e16;

struct Stoer_Wagner
{
	struct node
	{
		int i;
		LL w;
		node(int ii=0,LL ww=0):i(ii),w(ww){}
		bool operator <(const node &p)const
		{
			return w<p.w;
		}
	};
	
	struct edge
	{
		int v;
		LL w;
		edge(int vv=0,LL ww=0):v(vv),w(ww){}
	};
	
    edge e[MAXN][MAXN];
    int etop[MAXN];
    int ep[MAXN][MAXN];
    priority_queue<node> q;
    
    int n;
    
    LL w[MAXN];
    bool vis[MAXN],bin[MAXN];
    
    void init(int nn)
    {
        n=nn;
        mem(etop,0);
        mem(ep,-1);
        while(!q.empty())q.pop();
    }
    
    void AddEdge(int u,int v,LL w)
    {
        if(ep[u][v]==-1)
        {
            e[u][etop[u]]=edge(v,w);
            ep[u][v]=etop[u]++;
        }
        else e[u][ep[u][v]].w+=w;
        if(ep[v][u]==-1)
        {
            e[v][etop[v]]=edge(u,w);
            ep[v][u]=etop[v]++;
        }
        else e[v][ep[v][u]].w+=w;
    }
    
    LL Search(int &s,int &t)
    {
        mem(vis,0);
        mem(w,0);
        
        t=1;
        while(bin[t])t++;
        q.push(node(t,0));
        
        while(!q.empty())
        {
        	node p=q.top();
        	q.pop();
        	if(vis[p.i])continue;
        	vis[p.i]=true;
        	rep(i,0,etop[p.i])
        	{
        		int &v=e[p.i][i].v;
        		if(vis[v]||bin[v])continue;
        		w[v]+=e[p.i][i].w;
        		q.push(node(v,w[v]));
			}
            s=t;
            t=p.i;
        }
        
        return w[t];
    }
    
    LL Solve()
    {
        mem(bin,0);
        LL ret=INF;
        int s,t;
        rep(i,0,n-1)
        {
            LL pans=Search(s,t);
            ret=min(ret,pans);
            bin[t]=true;
            rep(i,0,etop[t])
            {
            	int &v=e[t][i].v;
                if(bin[v])continue;
                if(v==s)continue;
                AddEdge(s,v,e[t][i].w);
            }
        }
        return ret;
    }
}S;

int main()
{
    int n,m,s;
    while(scanf("%d%d%d",&n,&m,&s)==3)
    {
        if(n==0)break;
        S.init(n);
        rep(i,0,m)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            S.AddEdge(u,v,w);
        }
        printf("%lld\n",S.Solve());
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值