输出精确边缘的全局迷你切割算法

时间:2016-03-16 11:52:35

标签: algorithm graph

我正在寻找一种在无向图中找到全局迷你切割的算法。 我想输入一个图形和算法输出最小数量的边缘,通过剪切它们给定的图形可以分成两部分。

这是要求:

  1. 找到确切的边缘,而不仅仅是它们的编号。

  2. 最小切边应正确计算100%。

  3. 这是一张无向图。

  4. 算法应通过指示找到答案或未找到答案来终止。

  5. 我搜索了一些关于互联网的文章,发现Karger的最小割算法是随机的,其输出可能不是精确的最小割。我没有这样的算法。 我想计算精确的边(我需要知道它们是哪个边),其数量最小。

    我想听听一些建议,而我正在寻找这样的算法。 如果您的建议带有示例代码的算法介绍,那将是很好的。

    提前致谢。

1 个答案:

答案 0 :(得分:0)

我们可以使用最大流量算法来做到这一点,当我们计算图形的最大流量时,算法完成时饱和的边缘是最小切割的一部分。您可以阅读有关Max flow Min cut theorem 的更多信息。计算最大流量是一个相当标准的问题,有很多可用于该问题的多项式时间解决方案,您可以阅读更多关于它们的here

因此,为了总结算法,我们首先找到图形的最大流量,然后最小切割中的边缘是边缘上的流量等于边缘的容量(那些已经饱和的边缘) )。

因此解决最大流问题的方法之一是使用Ford Fulkerson algorithm,它在图中找到扩充路径,然后使用扩充路径中的最小边缘尝试使该扩充路径饱和,它重复此过程直到没有增加的路径。

要找到扩充路径,我们可以执行深度优先搜索或广度优先搜索。 Edmonds Karp的算法通过使用简单广度优先搜索来找到扩充路径。

我在下面编写了c ++代码来查找最大流量和最小切割量,找到最大流量的代码来自书籍" Steven Halim的竞争性编程"。

另请注意,由于图表是无向的,因此最小切割功能打印的所有边缘将是打印a -- bb -- a的两倍。

#include<iostream>
#include<vector>
#include<queue>
#include<utility>

#define MAXX 100
#define INF 1e9

using namespace std;

int s, t, flow, n, dist[MAXX], par[MAXX], AdjMat[MAXX][MAXX];  //Adjacency Matrix graph
vector< pair<int, int> > G[MAXX];   //adjacency list graph

void minCut(){
    for(int i = 0;i < n;i++){
        for(int j = 0;j < G[i].size();j++){
            int v = G[i][j].first;
            if(AdjMat[i][v] == 0){  //saturated edges
                cout << i << " " << v << endl;
            }
        }
    }
}

void augmentPath(int v, int minEdge){
    if(v == s){ flow = minEdge;return; }
    else if(par[v] != -1){
        augmentPath(par[v], min(minEdge, AdjMat[par[v]][v]));
        AdjMat[par[v]][v] -= flow;  //forward edges
        AdjMat[v][par[v]] += flow;  //backward edges
    }
}

void EdmondsKarp(){
    int max_flow = 0;
    for(int i= 0;i < n;i++) dist[i] = -1, par[i] = -1;
    while(1){
        flow = 0;
        queue<int> q;
        q.push(s);dist[s] = 0;
        while(!q.empty()){
            int u = q.front();q.pop();
            if(u == t) break;
            for(int i = 0;i < G[u].size();i++){
                int v = G[u][i].first;
                if(AdjMat[u][v] > 0 && dist[v] == -1){
                    dist[v] = dist[u] + 1;
                    q.push(v);
                    par[v] = u;
                }
            }
        }
        augmentPath(t, INF);
        if(flow == 0) break;    //Max flow reached, now we have saturated edges that form the min cut
        max_flow += flow;
    }
}

int main(){
    //Create the graph here, both as an adjacency list and adjacency matrix
    //also mark the source i.e "s" and sink "t", before calling max flow.

    return 0;
}