我正在尝试实现Karger的算法,以便在无向图中找到mincuts。我正在使用的图表有8条边,如t2 2D VEctor所示。
为此,我使用2D向量和图的邻接列表实现。
为了选择随机边缘,我实际上是随机选择了一个顶点,然后随机选择了另一个顶点来选择“随机”边缘。
然而,尽管我相信我已经正确地执行了所有步骤,但算法似乎没有给出一次运行的正确答案,并且多次运行时出现段错误...
我的代码如下:
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <random>
#include <algorithm>
#include <ctime>
#define MAX_ELEMENTS 201
using namespace std;
typedef int64_t int64;
//RNG Stuff
random_device rd;
mt19937_64 rng(rd());
uniform_int_distribution<int> uni(1, 9);
vector< vector<int64> > t(MAX_ELEMENTS);
vector < vector<int>> t2(9);
int mincut = 0;
void printVector(){
for (auto j : t2) {
for (auto l : j)
cout << l << " ";
cout << endl << "Hahaha " << j.size() << endl;
}
}
int randomNum() {
return uni(rng);
}
int KargersAlgorithm(void) {
int minOfTwo;
t2 = {{}, {1 ,2 ,3 ,4 ,7},
{2, 1 ,3 ,4},
{3, 1, 2, 4},
{4, 1, 2, 3, 5},
{5, 4, 6 ,7 ,8},
{6, 5, 7, 8},
{7, 1 ,5 ,6, 8},
{8, 5, 6, 7}};
while (t2.size() > 3) {
/*
* Randomly select vertices
*/
int nodeStart = 0;
while(nodeStart == 0)
nodeStart = randomNum() % t2.size();
int nodeEnd = 0;
while(nodeEnd == 0)
nodeEnd = randomNum() % t2[nodeStart].size();
//Insert all the edges from nodeEnd to nodeStart aka merge the vertices
t2[nodeStart].insert(t2[nodeStart].end(), t2[nodeEnd].begin(), t2[nodeEnd].end());
//Node renaming
for (int i = 1; i < t2[nodeEnd].size(); i++) { //For each vertex in nodeEnd
int foundEdge = t2[nodeEnd][i]; //Found an edge from nodeEnd to foundEdge,, so need to rename all the nodeEnd to nodeStart in this list
// cout<< "i: " << i << " FoundEdge: " << foundEdge << endl;
replace(t2[foundEdge].begin(), t2[foundEdge].end(), t2[nodeEnd][0], t2[nodeStart][0]); //Replace all the nodeEnd with t2[nodeStart][0] since that gives the ID number
}
//Remove self-loops from nodeStart
t2[nodeStart].erase(std::remove(t2[nodeStart].begin() + 1, t2[nodeStart].end(), t2[nodeStart][0]),
t2[nodeStart].end());
//Kill nodeEnd :(
t2.erase(t2.begin() + nodeEnd);
}
//printVector();
return min(t[1].size(), t[2].size());
}
int main(){
int min = 0;
for(int i =0; i < 1000000; i++) {
t2.clear();
int x = KargersAlgorithm();
if(x < min)min = x;
}
cout << min;
return 0;
}
算法的单次运行将以下内容作为最终数组(仅删除对KargersAlgorithm()函数的重复调用):
4 2 3 5 2 3 7
5 4 6 7 8 7 4 6 8 8 6
由于第一个元素表示顶点数,显然最后会留下顶点4和5。
好吧,这是我的疑惑:
有没有更好的方法在此实现中随机选择顶点?现在,因为t [0]因为我从1到8索引而没有任何内容,所以对t [0]的任何访问都会使程序崩溃。
输出是否正确?我觉得它应该像
4 5 5 5 5 5
5 4 4 4 4 4
但可能是我不理解......
我应该得到的实际最小值是多少?我怎样才能从输出中推断出它呢?现在我想的是两种尺寸中的最小尺寸,但似乎非常错误......
每当我尝试多次运行程序时,程序都会崩溃。以下是相同代码的ideone链接:
我理解我的理解可能不完整,但到目前为止,我在网上看到过的其他地方,我无法理解代码或地方不使用我所做的实现。
任何帮助将不胜感激。谢谢!
EDIT1:根据samgak和Patryk Obara的建议。我在每个函数调用的开头添加了一个clear(),并将t2数组大小的declration扩展为9(即使这可能并不重要),但即使这样它也会崩溃。根据CLion的说法,在第29次迭代中,由于findEdge中的垃圾负值,它在行replace()(代码中的第96行)崩溃,即使地址看似合法。所以我仍然感到困惑......提前谢谢!