Menemukan jalur pada graf yang tepinya acak

Kita mempunyai n simpul (di mana n kurang dari 100.000) dan m tepi acak (di mana m kurang dari 10.000.000). Kami ingin mencari jalur antara 2 simpul tertentu. Jika tidak ada jalur kami hanya akan mencetak -1. Algoritma saya adalah membangun pohon. Setiap simpul memiliki disjoint_index (i) yang menunjukkan bahwa semua simpul dengan disjoint_index (i), terhubung.

Nilai default disjoint_index adalah indeks setiap titik. Setelah menemukan tepi antara titik v dan u, saya periksa apakah keduanya terhubung. Jika mereka terhubung, saya tidak melakukan apa pun. Kalau tidak, saya mengubah disjoint_index dari u dan semua simpul yang terhubung ke u dengan fungsi bernama (dfs).

Berikut adalah kode fungsi untuk membangun pohon ini di c++:

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);
    }
}

Di sini Anda dapat melewati ciuman, Ini hanya fungsi yang mengembalikan dua simpul dan menunjukkan bahwa ada tepi antara u dan v.

disjoint_counter[i] menunjukkan berapa banyak simpul yang ada di grup terhubung i.

Setelah membangun pohon ini saya akan menemukan jalan dengan dfs sederhana. Batas waktunya adalah 1 detik dan saya mendapatkan Batas Waktu Terlampaui pada beberapa kasus pengujian.

Sunting: Memori terbatas jadi saya tidak bisa menyimpan semua tepinya. Memori maksimum yang dapat saya gunakan adalah 32MB.


person Pouya Esmaili    schedule 26.11.2019    source sumber
comment
Bisakah Anda menjelaskan mengapa Anda perlu membuat pohon untuk menemukan jalur antara dua simpul? Ada apa dengan BFS?   -  person BessieTheCookie    schedule 27.11.2019
comment
Ada 10.000.000 sisi dan semuanya acak, jadi saya harus menjalankan ulang perulangan for setiap kali untuk menemukan simpul yang berdekatan dari setiap simpul, skenario yang lebih buruk, Ini akan memakan waktu 100.000 kali yang jauh lebih lambat daripada algoritma saya saat ini.   -  person Pouya Esmaili    schedule 27.11.2019
comment
Apa maksud Anda ketika Anda mengatakan ujung-ujungnya acak? Apakah Anda tidak diberi sisi pada grafik?   -  person BessieTheCookie    schedule 27.11.2019
comment
Saat saya memanggil fungsi ciuman, Ini memberi saya 2 simpul dan ada tepi di antara keduanya. Maaf saya lupa mengatakan bahwa ingatan saya terbatas dan saya tidak dapat menyimpan semua sisi.   -  person Pouya Esmaili    schedule 27.11.2019


Jawaban (1)


Saya menggunakan algoritma disjoint set union, yang mengembangkan kecepatan.

person Pouya Esmaili    schedule 27.12.2019