Stoer Wagner 算法主要是解决无向图最小割的问题。
给定一张无向图,每一条边都有其花费,求最少能使这张图不连通应割掉的边数。
原作者论文,侵删
<h1>解题思路</h1>
首先我们可以使用网络流暴力跑,也就是随机一个源点然后枚举汇点跑最大流那种,但是时间复杂度有点高,上界是 $O(n^3m)$。
于是 就有了 Stoer Wagner 算法来解决这个问题。
我们先描述一下这个算法的一般流程:
- $min = INF$,固定一个顶点 $P$
- 从点 $P$ 用 “类似” prim 的算法扩展出 “最大生成树” ,记录最后扩展的顶点和最后扩展的边
- 计算最后扩展到的顶点的切割值(即与此顶点相连的所有边权和),若比 min 小更新 min
- 合并最后扩展的那条边的两个端点为一个顶点(当然他们的边也要合并,这个好理解吧?)
- 转到 $2$,合并 N-1 次后结束
- min 即为所求,输出 min
相信大家看到这里一定是懵逼的...那么建议大家先阅读代码,然后结合论文食用。
<h1>代码</h1>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <climits>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define Re register
#define LL long long
#define U unsigned
#define FOR(i,a,b) for(Re int i = a;i <= b;++i)
#define ROF(i,a,b) for(Re int i = a;i >= b;--i)
#define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c)
#define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c)
#define CLR(i,a) memset(i,a,sizeof(i))
#define BR printf("--------------------n")
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int MAXN = 1000+5;
int fMAXN,dist[MAXN];
bool vis[MAXN],del[MAXN];
int N,M;
inline void init(){
CLR(f,0);CLR(del,false);
}
int contract(int &s,int &t){
int min=0;
CLR(dist,0);CLR(vis,0);
FOR(i,1,N){
int k = -1,max = -1;
FOR(j,1,N){
if(!del[j] && !vis[j] && dist[j] > max){
k = j;max = dist[j];
}
}
if(k == -1) return min;
s = t,t = k;
min = max;
vis[k] = true;
FOR(j,1,N){
if(!del[j] && !vis[j]) dist[j] += fk;
}
}
return min;
}
int SW(){
int min = INT_MAX;
FOR(i,1,N-1){
int s,t;
min = std::min(min,contract(s,t));
del[t] = true;
if(min == 0) return 0;
FOR(j,1,N) if(!del[j]) fs = (fj += fj);
}
return min;
}
inline void Solve(){
init();
FOR(i,1,M){
int u,v,w;scanf("%d%d%d",&u,&v,&w);
u++;v++;
fu = (fv += w);
}
printf("%dn",SW());
}
int main(){
while(~scanf("%d%d",&N,&M)) Solve();
return 0;
}