# 全局最小割 stoer-wagner与karger-stein算法

stoer-wagner算法

const int maxn = 550;
const int inf = 1000000000;
int n, r;
int edge[maxn][maxn], dist[maxn];
bool vis[maxn], bin[maxn];
void init() {
memset(edge, 0, sizeof(edge));
memset(bin, false, sizeof(bin));
}
int contract( int &s, int &t ) {        // Find s,t
memset(dist, 0, sizeof(dist));
memset(vis, false, sizeof(vis));
int i, j, k, mincut, maxc;
for(i = 1; i <= n; i++) {
k = -1;
maxc = -1;
for(j = 1; j <= n; j++)if(!bin[j] && !vis[j] && dist[j] > maxc) {
k = j;
maxc = dist[j];
}
if(k == -1)return mincut;
s = t;
t = k;
mincut = maxc;
vis[k] = true;
for(j = 1; j <= n; j++)if(!bin[j] && !vis[j])
dist[j] += edge[k][j];
}
return mincut;
}

int Stoer_Wagner() {
int mincut, i, j, s, t, ans;
for(mincut = inf, i = 1; i < n; i++) {
ans = contract( s, t );
bin[t] = true;
if(mincut > ans)mincut = ans;
if(mincut == 0)return 0;
for(j = 1; j <= n; j++)if(!bin[j])
edge[s][j] = (edge[j][s] += edge[j][t]);
}
return mincut;
}

--------------------------------------------------------------------------------------------------------

对于特殊的所有边权值都为1的全局最小割，存在复杂度更低但常数较大的karger-stein算法

在实际测试中的表现

10次Karger-stein     stoer-wagner

n=2000　　　　　  40s 　　　　　　10s

n=5000　　　　　  340s　　　　　　134s

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#define ULL unsigned long long
#define LDB long double
using namespace std;

ULL sed=233;
int top,deg[5010],b[5010][5010],totdeg,n,m,succ[5010],prev[5010],faqcnt=0;
map <int,int> mp;

struct data{
int x,y,k,num;
}sta[5000*5000+1];

ULL ran(){
sed*=1280313;sed+=12413;sed^=123893;
return(sed);
}

void restore(int tar){
while (top>tar){
data t=sta[top];top--;
int x=t.x,y=t.y,i=t.k,num=t.num;
if (t.k==-1){
deg[x]+=num;deg[y]+=num;
b[x][y]=b[y][x]=num;
totdeg+=2*num;
succ[prev[x]]=x;prev[succ[x]]=x;
}else{
deg[x]+=num;deg[y]-=num;
b[y][i]=(b[i][y]-=num);
b[x][i]=b[i][x]=num;
}
}
}

void contract(int x,int y){
sta[++top]=(data){x,y,-1,b[x][y]};
deg[x]-=b[x][y];deg[y]-=b[x][y];
totdeg-=2*b[x][y];
b[x][y]=b[y][x]=0;
prev[succ[x]]=prev[x];succ[prev[x]]=succ[x];
for (int i=0;i<=n;i=succ[i]) if (b[x][i]){
sta[++top]=(data){x,y,i,b[x][i]};
deg[x]-=b[x][i];deg[y]+=b[x][i];
b[y][i]=(b[i][y]+=b[x][i]);
b[x][i]=b[i][x]=0;
}
}

void del(){
int tar=ran()%totdeg+1,x,y;
for (x=0;tar>deg[x];tar-=deg[x],x=succ[x]);
for (y=0;tar>b[x][y];tar-=b[x][y],y=succ[y]);
contract(x,y);
}

int slowsolve(int po){
int ttop=top;
for (int i=1;i<=po-2;i++) del();
int ret=totdeg/2;
restore(ttop);
return(ret);
}

int fastsolve(int po){
int ttop=top,ret=1e9;mp[po]++;
if (po<=20){
int ret=1e9;
for (int i=1;i<=100;i++){
ret=min(ret,slowsolve(po));
restore(ttop);
}
return(ret);
}

int tar=ceil(1+po/sqrt(2));
for (int i=1;i<=po-tar;i++) del();
ret=min(ret,fastsolve(tar));
restore(ttop);

for (int i=1;i<=po-tar;i++) del();
ret=min(ret,fastsolve(tar));
restore(ttop);
return(ret);
}

int main(){
scanf("%d%d",&n,&m);
prev[n+1]=n;succ[0]=1;
for (int i=1;i<=n;i++) prev[i]=i-1,succ[i]=i+1;
for (int i=1;i<=m;i++){
int t1,t2;
scanf("%d%d",&t1,&t2);
deg[t1]++;deg[t2]++;b[t1][t2]++;b[t2][t1]++;
totdeg+=2;
}

int ans=1e9;
for (int i=1;i<=10;i++){
int t=fastsolve(n);
ans=min(ans,t);
printf("%d\n",t);
}

printf("%d\n",ans);
}

posted @ 2017-12-19 20:34 z1j1n1 阅读(...) 评论(...) 编辑 收藏