POJ2914

POJ2914
无向图的最小割


题意:给你一个无向图,然后去掉其中的n条边,使之形成两个连通分量,也即原无向图不连通,求n的最小值。


输入:


m(无向图点集),n(无向图边集)
a,b,c(a,b两点之间流量)


输出:
n最小值


按照算法与实现上的Stoer-Wagner算法求解,原理不愿细究,知道接口能用就行,可以优化,用优先队列能将

复杂度减少到(nm+(n^2)*logn)

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int max1=512;
int g[max1][max1];
int b[max1],dist[max1];
int n,m;
/*
struct stoer_wagner
{
int n,g[max][max],b[max],dist[max];
void init(int nn,int w[max][max])
{
int i,j;
n=nn;
for(int i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
g[i][j]=w[i][j];
}
}
*/


int min_cut_phase(int ph,int &x,int &y)
{
	int i,j,t;
	b[t=1]=ph;
	for(i=1;i<=n;i++)
		if(b[i]!=ph)
			dist[i]=g[1][i];
		for(i=1;i<n;i++)
		{
			x=t;
			for(t=0,j=1;j<=n;j++)
				if(b[j]!=ph&&(!t||dist[j]>dist[t]))
					t=j;
				b[t]=ph;
				for(j=1;j<=n;j++)
					if(b[j]!=ph)
						dist[j]+=g[t][j];
		}
		return y=t,dist[t];
}


void merge(int x,int y)
{
	int i;
	if(x>y) swap(x,y);
	for(i=1;i<=n;++i)
		if(i!=x&&i!=y)
			g[i][x]+=g[i][y],g[x][i]+=g[y][i];
		if(y==n)
			return ;
		for(i=1;i<n;++i) if(i!=y){
			swap(g[i][y],g[i][n]);
			swap(g[y][i],g[n][i]);
		}
}


void min_cut()
{
	int ret=0x3fffffff,i,x,y;
	memset(b,0,sizeof(b));
	for(i=1;n>1;++i,n--){
		ret=min(ret,min_cut_phase(i,x,y));
		merge(x,y);
	}
	printf("%d\n",ret);
}


int main()
{
    while(scanf("%d%d",&n,&m)==2){
        memset(g,0,sizeof(g));
        while(m--){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            a++,b++;
            g[a][b]+=c;
            g[b][a]+=c;
        }
		min_cut();
    }
    return 0;
}


posted @ 2015-07-14 12:44  __夜风  阅读(260)  评论(0编辑  收藏  举报