Хобрук: Ваш путь к мастерству в программировании

DFS — поиск минимального остовного дерева в графе

l - список adiacency
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);
        }
    }
}
17.06.2013

  • используйте скобки, чтобы заказать код. Я сомневаюсь, что оператор if делает то, что вы хотите сделать. 18.06.2013
  • Не будет ли слишком много минимального полного примера и более подробного описания неправильных результатов? 18.06.2013
  • Хорошо, я написал несколько примеров данных и немного отрефакторил код. 18.06.2013
  • Я только что видел это и отредактировал вывод, но теперь это еще более странно. 18.06.2013
  • 4, так как вершин 4. 18.06.2013
  • for(int i = 0; i ‹ cols; i++) Visit[i] = false; -› for(int i = 1; i ‹= cols; i++) Visit[i] = false; ??? 18.06.2013
  • нет, это ничего не меняет. 18.06.2013
  • На самом деле я обнаружил, что список смежности рассматривает вершины как 0-3, а не 1-4... это что-то меняет? 18.06.2013
  • Когда я это обнаружил, я сначала уменьшил x, но результаты все равно неверны. 18.06.2013
  • Поскольку это неориентированный граф, в этом примере x должен быть равен 0... я не вижу никакой другой проблемы... вы должны указать вывод всех dfst[0..3] 18.06.2013

Ответы:


1

Я работал с вашим кодом, он кажется правильным. Однако имейте в виду, что существует несколько деревьев 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

Если это происходит, возможно, попробуйте рекурсивный подход.

Тем не менее, просмотр некоторых образцов ввода и вывода поможет ответить на этот вопрос, поскольку это может быть не ваша проблема.

EDIT: я должен уточнить, что несколько деревьев DFS в графе с циклом применяются, когда цикл является двунаправленным, например, с неориентированным графом. Дело в том, что вы можете найти дерево DFS, которое также является правильным, но не таким, как то, которое было определено как правильное.

РЕДАКТИРОВАТЬ (снова): Еще одна проблема, которая у вас может возникнуть: ваш алгоритм, по-видимому, предназначен для неориентированных графов, поскольку в вашем коде есть dfst[x].push_back(y); dfst[y].push_back(x);, но ваш входной граф, приведенный в вашем примере, выглядит так, как будто он направлен. Удаление второго оператора (dfst[y].push_back(x);) должно исправить это.

17.06.2013
  • @ user2489034 Вы уже нашли решение? Просто проверяю 18.06.2013
  • Я потерял надежду, пока не увидел ваше второе редактирование - удаление этой второй строки сработало: D Спасибо! 19.06.2013

  • 2

    Код выглядит немного запутанным, на самом деле я думал, что сначала это 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);
        }
    }
    
    17.06.2013
  • Это должно быть if (!visited[*i]) внутри цикла for. Но это не изменило бы результат, а только сделало бы его более эффективным. 18.06.2013
  • Новые материалы

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

    Обзор 20 основных и современных методов работы с массивами в JavaScript
    Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

    Да, но я чувствую необходимость указать, что это или не единственные два.
    Да, но я чувствую необходимость указать, что это или не единственные два. Обучение с подкреплением (в качестве примера) также является важным.