全局最小割Stoer-Wagner算法 时间复杂度(o^3)

来源:互联网 发布:pla pocket算法 编辑:程序博客网 时间:2024/06/07 06:54

以前做过一道全局最小割,今天复习时看到了,先记录下来。



给你一个N个点M条边的无向图,问它的最小割。


全局最小割Stoer-Wagner算法实现 时间复杂度O(N^3) 优化后可以达到O(N^2log(N))
用wage数组记录点的连通度,vis数组标记点是否在集合里面,In数组表示点被其它点合并。


分两步
一:找到S - T的最小割Mincut,其中S 和 T为最后并入集合的两个点。
1,初始化数组vis 和 wage;
2,遍历所有不在集合且没有被合并的点,找到最大wage值的点Next,并记录Mincut、S和T;
3,Next并入集合,叠加与Next相连的所有点(不在集合 且 没有被合并),更新这些点的wage值;
4,重复操作2和3一共N次 或者 找不到新的Next值时 跳出,返回Mincut;


二、找全局最小割ans,需要重复第一步N-1次,因为每次合并一个点,最多合并N-1个点;
1,每次对返回的Mincut,更新ans = min(ans, Mincut),当然ans为0时,说明图不连通;
2,把点T合并到S点,操作有:对 所有没有被合并的点j,Map[S][j] += Map[T][j]。



代码:


#include <cstdio>#include <cstring>#include <algorithm>#define MAXN 500+10#define INF 0x3f3f3f3fusing namespace std;int Map[MAXN][MAXN];bool vis[MAXN];//是否已并入集合int wage[MAXN];//记录每个点的连通度bool In[MAXN];//该点是否已经合并到其它点int N, M;void getMap(){    memset(Map, 0, sizeof(Map));    int a, b, c;    for(int i = 0; i < M; i++)    {        scanf("%d%d%d", &a, &b, &c);        a++, b++;        Map[a][b] += c;        Map[b][a] += c;    }}int S, T;//记录每次找s-t割  所遍历的最后两个点int work(){    int Mincut;//每一步找到的s-t割    memset(wage, 0, sizeof(wage));    memset(vis, false, sizeof(vis));    int Next;    for(int i = 1; i <= N; i++)    {        int Max = -INF;        for(int j = 1; j <= N; j++)        {            if(!In[j] && !vis[j] && Max < wage[j])//找最大的wage值            {                Next = j;                Max = wage[j];            }        }        if(Next == T) break;//找不到点 图本身不连通        vis[Next] = true;//标记 已经并入集合        Mincut = Max;//每次更新        S = T, T = Next;// 记录前、后点        for(int j = 1; j <= N; j++)//继续找不在集合 且 没有被合并过的点        {            if(In[j] || vis[j]) continue;            wage[j] += Map[Next][j];//累加 连通度        }    }    return Mincut;}int Stoer_wagner(){    memset(In, false, sizeof(In));    int ans = INF;    for(int i = 0; i < N-1; i++)    {        ans = min(ans, work());        if(ans == 0) return 0;//本身不连通        In[T] = true;        for(int j = 1; j <= N; j++)//把T点合并到S点        {            if(In[j]) continue;//已经合并            Map[S][j] += Map[T][j];            Map[j][S] += Map[j][T];        }    }    return ans;}int main(){    while(scanf("%d%d", &N, &M) != EOF)    {        getMap();        printf("%d\n", Stoer_wagner());    }    return 0;}


0 0