最小割Stoer_Wagner算法,网上到处都有这个算法的步骤,实现起来也比较简单。
刚刚才理解最小割就是最大流,之所以不用最大流算法,是因为最大流算法有确定的源点和汇点,但是求最小割没有指明源点和汇点;
如果枚举每个源点和汇点加上最大流的算法时间复杂度太高O(n^4),用这个算法时间复杂度在O(n^3)。给个链接介绍给大家:http://www.cnblogs.com/ylfdrib/archive/2010/08/17/1801784.html
代码:
#include<iostream>
#include<string.h>
#define maxn 505
#define INF 0x7fffffff
using namespace std;
int map[maxn][maxn],dist[maxn];
int n,m,mimcut,S,T;
bool educed[maxn],vis[maxn];
void Prim() //最大生成树
{
int i,j,pt,mx;
memset(dist,0,sizeof(dist));
memset(vis,false,sizeof(vis));
S=T=-1;
for( i=0;i<n;i++){
mx=-1;
for( j=0;j<n;j++)
if( !vis[j]&&!educed[j]&&dist[j]>mx)
pt=j, mx=dist[j];
if(T==pt) return;
S=T, T=pt; //最后两个扩展的顶点。
vis[T]=true;
mimcut=mx;
for( j=0;j<n;j++)
if( !educed[j]&&!vis[j])
dist[j]+=map[T][j];
}
}
int Stoer_Wagner()
{
memset(educed,false,sizeof(educed));
int ans=INF,i,j;
for( i=1;i<n;i++){
Prim();
if( mimcut<ans) ans=mimcut;
educed[T]=true; //缩点,将最后扩展的两个点缩成一点。
for( j=0;j<n;j++){
if( !educed[j]){
map[S][j]+=map[T][j];
map[j][S]+=map[j][T];
}
}
}
return ans;
}
int main()
{
int a,b,c;
while( scanf("%d%d",&n,&m)!=EOF){
memset(map,0,sizeof(map));
while( m--){
scanf("%d%d%d",&a,&b,&c);
map[a][b]+=c;
map[b][a]+=c;
}
printf("%d\n",Stoer_Wagner());
}
return 0;
}