Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Karger的算法不适用于单次运行,而适用于多次运行_C++_Algorithm_C++11_Random_Graph - Fatal编程技术网

C++ Karger的算法不适用于单次运行,而适用于多次运行

C++ Karger的算法不适用于单次运行,而适用于多次运行,c++,algorithm,c++11,random,graph,C++,Algorithm,C++11,Random,Graph,我正在尝试实现Karger的算法来寻找am无向图中的最小割。我使用的图形有8条边,如t2 2D向量所示 为此,我使用了2D向量和图的邻接列表实现 对于选择随机边,我实际上随机选择了一个顶点,然后从其边列表中随机选择另一个顶点来选择随机边 然而,即使我相信我正确地遵循了所有的步骤,该算法似乎并没有为一次运行给出正确的答案,并且在多次运行中出现故障 我的代码如下: #include <iostream> #include <vector> #include <fstre

我正在尝试实现Karger的算法来寻找am无向图中的最小割。我使用的图形有8条边,如t2 2D向量所示

为此,我使用了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;
}
由于第一个元素表示顶点编号,显然顶点4和5最后被保留

那么,以下是我的疑问:

在这个实现中,有没有更好的方法来随机选择顶点?现在,由于t[0]在从1到8的索引中没有任何内容,因此对t[0]的任何访问都会使程序崩溃

我得到的输出正确吗?我觉得应该是这样的

45555

544

但可能是我不太明白

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

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

我知道我的理解可能不完整,但到目前为止,在我在web上看到的其他地方,要么我无法理解代码,要么这些地方没有使用我的实现

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


编辑1:根据samgak和Patryk Obara的建议。我在每个函数调用的开头添加了一个clear,并将t2数组大小的declr扩展到9,尽管这可能没什么大不了的,但即使这样,它也会崩溃。根据CLion的说法,在第29次迭代中,由于foundEdge中的垃圾负值,它在代码中的替换行96处崩溃,即使地址看起来是合法的。所以我还是很困惑。。。提前谢谢

我的建议是通过调试器运行它,看看它在哪里崩溃,然后从那里开始。第一个崩溃是line,在这里填充t2,将9个元素放入一个大小为8的向量中。第二次崩溃发生在直线上,即合并顶点的位置。不幸的是,我现在没有时间阅读您的实现并跟进。在KargersAlgorithm函数开始时调用clear on your vectors我添加了您的两个建议,并使用调试器检查了它何时何地崩溃。谢谢你的建议!还有一点意见:连接两个向量并不是合并两个顶点的最佳方法。毕竟,您希望删除重复的顶点,这似乎是您的算法中缺少的-您可能希望对邻接列表使用std::set-合并两个集合将自动删除重复的顶点。嗯,我明白了。但是,在删除重复项的同时合并它们不会删除存在的任何平行边吗?我的建议是通过调试器运行此操作,查看它在哪里崩溃,然后从那里开始。第一个崩溃是line,在这里填充t2,将9个元素放入一个大小为8的向量中。第二次崩溃发生在直线上,即合并顶点的位置。不幸的是,我现在没有时间阅读您的实现并跟进。在KargersAlgorithm函数开始时调用clear on your vectors我添加了您的两个建议,并使用调试器检查了它何时何地崩溃。谢谢你的建议!还有一点意见:连接两个向量并不是合并两个顶点的最佳方法。毕竟,您希望删除重复的顶点,这似乎是您的算法中缺少的-您可能希望对邻接列表使用std::set-合并两个集合将自动删除重复的顶点。嗯,我明白了。但是,在删除重复项时合并它们不会删除存在的任何平行边吗?
4 2 3 5 2 3 7
5 4 6 7 8 7 4 6 8 8 6