DFS - 在图中查找最小生成树

时间:2013-06-17 20:21:03

标签: algorithm graph

l - adiacency list
x - 起始顶点
dfst,q - 顶点大小的空数组

std::list <int> q;
std::vector<bool> visited(cols + 1); 
for(int i = 0; i < cols; i++) visited[i] = false;
visited[x] = true;
if(!l[x].empty())
for(std::list<int>::iterator i = l[x].begin(); i != l[x].end(); i++)
{
    q.push_back(x); q.push_back(* i);
}
while(!q.empty())
{
    y = q.back(); q.pop_back();
    x = q.back(); q.pop_back();
    if(!visited[y])
    {
        visited[y] = true;
        if(!l[y].empty())
        for(std::list<int>::iterator i = l[y].begin(); i != l[y].end(); i++)
        {
            q.push_back(y); q.push_back(* i);
        }
        dfst[x].push_back(y);
        dfst[y].push_back(x);
    }
}

我只是看不出为什么会给出错误的结果...我不知道你是否熟悉这个算法,但如果你是,我希望你能看到这里的错误。

编辑:

邻接表是:
1:2,3 2:3
3:4
4:3

MST应该是这样的:
1:2,3 3:4

但相反,它是:
2:3
3:2,4 4:3

目前的代码是:(我在需要的地方使用括号):

std::list <int> q;
std::vector<bool> visited(cols + 1); 
for(int i = 0; i < cols; i++) visited[i] = false;
visited[x] = true;
if(!l[x].empty())
{
    for(std::list<int>::iterator i = l[x].begin(); i != l[x].end(); i++)
    {
        q.push_back(x); q.push_back(* i);
    }
    while(!q.empty())
    {
        y = q.back(); q.pop_back();
        x = q.back(); q.pop_back();
        if(!visited[y])
        {
            visited[y] = true;
            if(!l[y].empty())
            for(std::list<int>::iterator i = l[y].begin(); i != l[y].end(); i++)
            {
                if(!visited[*i])
                {q.push_back(y); q.push_back(* i);}
            }
            dfst[x].push_back(y);
            dfst[y].push_back(x);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

代码看起来有点混乱,实际上我认为它的BFS首先......但它的DFS 您应该在添加到堆栈(列表后面)之前检查节点是否已被访问

while(!q.empty())
{
    y = q.back(); q.pop_back();
    x = q.back(); q.pop_back();
    if(!visited[y])
    {
        visited[y] = true;
        if(!l[y].empty())
        for(std::list<int>::iterator i = l[y].begin(); i != l[y].end(); i++)
        {
            if(!visited[*i])
            {q.push_back(y); q.push_back(* i);}
        }
        dfst[x].push_back(y);
        dfst[y].push_back(x);
    }
}

答案 1 :(得分:0)

我处理了您的代码,看起来是正确的。 但是,请记住,如果输入树有一个循环,则有多个DFS树。您获得的树取决于您处理顶点的顺序。也许你的输入有一个循环?如果是这样,您的代码可能会按照与解决方案中处理顺序不同的顺序处理节点。

例如,对输入树采用以下邻接列表,其中节点是字母:

a: b,c
b: a,d
c: a,c,e
d: b,c,e
e: c,d

从a开始,如果我们根据字母顺序查看下一个节点的邻接列表,我们得到以下DFS树:

a: b
b: a,d
c: d,e
d: b,d
e: c

但是,使用您的算法,我们得到以下结果:

a: c
b: d
c: a,e
d: b,e
e: c,d

如果发生这种情况,也许可以尝试一种递归方法。

看到一些样本输入和输出会有助于进一步解决这个问题,因为这可能不是你的问题。

编辑:我应该澄清,带有循环的图形中的多个DFS树适用于循环是双向的,例如使用无向图。关键是,您可能会发现DFS树也是正确的,但与已被识别为正确的DFS树不同。

编辑(再次):您可能遇到的另一个问题:您的算法似乎是针对无向图的,因为您的代码中有dfst[x].push_back(y); dfst[y].push_back(x);,但是您的输入图是示例看起来像是直接的。删除第二个语句(dfst[y].push_back(x);)应该更正此