我正在寻找一种在无向图中找到全局迷你切割的算法。 我想输入一个图形和算法输出最小数量的边缘,通过剪切它们给定的图形可以分成两部分。
这是要求:
找到确切的边缘,而不仅仅是它们的编号。
最小切边应正确计算100%。
这是一张无向图。
算法应通过指示找到答案或未找到答案来终止。
我搜索了一些关于互联网的文章,发现Karger的最小割算法是随机的,其输出可能不是精确的最小割。我没有这样的算法。 我想计算精确的边(我需要知道它们是哪个边),其数量最小。
我想听听一些建议,而我正在寻找这样的算法。 如果您的建议带有示例代码的算法介绍,那将是很好的。
提前致谢。
答案 0 :(得分:0)
我们可以使用最大流量算法来做到这一点,当我们计算图形的最大流量时,算法完成时饱和的边缘是最小切割的一部分。您可以阅读有关Max flow Min cut theorem 的更多信息。计算最大流量是一个相当标准的问题,有很多可用于该问题的多项式时间解决方案,您可以阅读更多关于它们的here。
因此,为了总结算法,我们首先找到图形的最大流量,然后最小切割中的边缘是边缘上的流量等于边缘的容量(那些已经饱和的边缘) )。
因此解决最大流问题的方法之一是使用Ford Fulkerson algorithm,它在图中找到扩充路径,然后使用扩充路径中的最小边缘尝试使该扩充路径饱和,它重复此过程直到没有增加的路径。
要找到扩充路径,我们可以执行深度优先搜索或广度优先搜索。 Edmonds Karp的算法通过使用简单广度优先搜索来找到扩充路径。
我在下面编写了c ++代码来查找最大流量和最小切割量,找到最大流量的代码来自书籍" Steven Halim的竞争性编程"。
另请注意,由于图表是无向的,因此最小切割功能打印的所有边缘将是打印a -- b
和b -- 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;
}