Поиск пути в графе со случайными ребрами

У нас есть n вершин (где n меньше 100 000) и m случайных ребер (где m меньше 10 000 000). Мы хотим найти путь между двумя заданными вершинами. Если пути нет, мы просто напечатаем -1. Мой алгоритм состоит в том, чтобы построить дерево. Каждая вершина имеет индекс disjoint_index (i), который показывает, что все вершины с индексом disjoint_index (i) связаны.

Значение по умолчанию disjoint_index — это индекс каждой вершины. Найдя ребро между вершинами v и u, я проверяю, соединены ли они. Если они подключены, я ничего не делаю. В противном случае я изменяю disjoint_index u и всех вершин, связанных с u, с помощью функции с именем (dfs).

Вот код функции для построения этого дерева на С++:

struct vertex{
    int disjoint_index;
    vector<int> adjacent;
};

void build_tree(int m, int s, int e)
{
    for(int i = 0; i < m; i++)
    {
        int u = kiss() % n;
        int v = kiss() % n;

        if(disjoint_counter[u] > disjoint_counter[v])
        {
            int temp = u;
            u = v;
            v = temp;
        }//counter v > u

        if(ver[v].disjoint_index != ver[u].disjoint_index)
        {
            ver[v].adjacent.push_back(u);
            ver[u].adjacent.push_back(v);

            dfs(v, u, ver[v].disjoint_index);

            disjoint_counter[v] += disjoint_counter[u];
        }

        if(ver[s].disjoint_index == ver[e].disjoint_index)
            return;
    }
}

void dfs(int parent, int v, int d)
{
    ver[v].disjoint_index = d;
    for(int i = 0; i < ver[v].adjacent.size(); i++)
    {
        if(ver[v].adjacent[i] == parent)
            continue;
        dfs(v, ver[v].adjacent[i], d);
    }
}

Здесь можно пропустить поцелуй, это просто функция, которая возвращает две вершины и показывает, что между u и v есть ребро.

disjoint_counter[i] показывает, сколько вершин находится в связанной группе i.

После построения этого дерева я найду путь с помощью простого dfs. Ограничение по времени составляет 1 с, и я получаю превышение лимита времени в некоторых тестовых случаях.

Изменить: память ограничена, поэтому я не могу сохранить все края. Максимальный объем памяти, который я могу использовать, составляет 32 МБ.


person Pouya Esmaili    schedule 26.11.2019    source источник
comment
Не могли бы вы пояснить, зачем нужно строить дерево, чтобы найти путь между двумя вершинами? Что не так с БФС?   -  person BessieTheCookie    schedule 27.11.2019
comment
Существует 10 000 000 ребер, и они совершенно случайны, поэтому мне приходится каждый раз перезапускать цикл for, чтобы найти соседние вершины каждой вершины, в худшем случае это займет 100 000 раз, что намного медленнее, чем мой текущий алгоритм.   -  person Pouya Esmaili    schedule 27.11.2019
comment
Что вы имеете в виду, когда говорите, что ребра случайны? Вам не заданы ребра в графе?   -  person BessieTheCookie    schedule 27.11.2019
comment
Когда я вызываю функцию поцелуя, она дает мне 2 вершины, между которыми есть ребро. Извините, я забыл сказать, что моя память ограничена, и я не могу сохранить все края.   -  person Pouya Esmaili    schedule 27.11.2019


Ответы (1)


Я использовал алгоритм объединения непересекающихся множеств, он развивал скорость.

person Pouya Esmaili    schedule 27.12.2019