Karger的算法不适用于单次运行和多次运行的崩溃

时间:2016-07-27 09:44:43

标签: c++ algorithm c++11 random graph

我正在尝试实现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。

好吧,这是我的疑惑:

  1. 有没有更好的方法在此实现中随机选择顶点?现在,因为t [0]因为我从1到8索引而没有任何内容,所以对t [0]的任何访问都会使程序崩溃。

  2. 输出是否正确?我觉得它应该像

    4 5 5 5 5 5

    5 4 4 4 4 4

  3. 但可能是我不理解......

    1. 我应该得到的实际最小值是多少?我怎样才能从输出中推断出它呢?现在我想的是两种尺寸中的最小尺寸,但似乎非常错误......

    2. 每当我尝试多次运行程序时,程序都会崩溃。以下是相同代码的ideone链接:

    3. http://ideone.com/LsGhiO

      我理解我的理解可能不完整,但到目前为止,我在网上看到过的其他地方,我无法理解代码或地方不使用我所做的实现。

      任何帮助将不胜感激。谢谢!

      EDIT1:根据samgak和Patryk Obara的建议。我在每个函数调用的开头添加了一个clear(),并将t2数组大小的declration扩展为9(即使这可能并不重要),但即使这样它也会崩溃。根据CLion的说法,在第29次迭代中,由于findEdge中的垃圾负值,它在行replace()(代码中的第96行)崩溃,即使地址看似合法。所以我仍然感到困惑......提前谢谢!

0 个答案:

没有答案