Mostovi i artikulacioni čvorovi

Lekcija 16 od 17 · Grafovi i stabla

Most je grana čijim uklanjanjem se graf raspada na dva dela, a artikulacioni čvor je čvor čijim uklanjanjem se to dešava. To su „slabe tačke“ mreže: jedan put, jedan ruter ili jedna raskrsnica od koje zavisi povezanost. Svi se nalaze jednim DFS obilaskom (Tarjanov algoritam).

Pre nego što počneš: potrebno predznanje – DFS.
Kako da učiš: svaki primer prekucaj i pokreni, a zadatke na kraju prvo reši sam/a; uputstvo i rešenje otvori tek posle toga. Svi programi su u C++-u.

Primer

  1 --- 2         5 --- 6
   \   /          |
    \ /           |
     3 --------- 4

Grane 1–2, 2–3, 1–3 čine ciklus, pa nijedna od njih nije most. Grane 3–4, 4–5 i 5–6 su mostovi. Artikulacioni čvorovi su 3, 4 i 5.

Ideja: vreme ulaska i low

Tokom DFS-a svakom čvoru dodelimo tin[v] – redni broj ulaska. Zatim računamo low[v]: najmanji tin do koga se iz podstabla čvora v može stići, koristeći grane DFS stabla nadole i jednu „povratnu“ granu ka već posećenom čvoru.

  • Grana v – u (u je dete u DFS stablu) je most ako je low[u] > tin[v]: iz podstabla čvora u nema drugog puta do v ili iznad njega.
  • Čvor v (koji nije koren) je artikulacioni ako ima dete u sa low[u] >= tin[v].
  • Koren DFS stabla je artikulacioni ako ima bar dva deteta u DFS stablu.

Program

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<vector<int>> graf;
vector<int> tin, low;
vector<bool> artikulacioni;
vector<pair<int, int>> mostovi;
int vreme = 0;

void dfs(int v, int roditelj) {
    tin[v] = low[v] = ++vreme;
    int dece = 0;
    for (int u : graf[v]) {
        if (u == roditelj) continue;
        if (tin[u]) {                              // povratna grana ka posećenom čvoru
            low[v] = min(low[v], tin[u]);
        } else {                                   // grana DFS stabla
            dfs(u, v);
            dece++;
            low[v] = min(low[v], low[u]);
            if (low[u] > tin[v]) mostovi.push_back({min(u, v), max(u, v)});
            if (roditelj != 0 && low[u] >= tin[v]) artikulacioni[v] = true;
        }
    }
    if (roditelj == 0 && dece >= 2) artikulacioni[v] = true;   // koren
}

int main() {
    int n, m;
    cin >> n >> m;
    graf.resize(n + 1);
    tin.assign(n + 1, 0);
    low.assign(n + 1, 0);
    artikulacioni.assign(n + 1, false);
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        graf[u].push_back(v);
        graf[v].push_back(u);
    }
    for (int v = 1; v <= n; v++)
        if (!tin[v]) dfs(v, 0);                    // graf može biti nepovezan
    sort(mostovi.begin(), mostovi.end());
    cout << "Mostovi:";
    for (auto [a, b] : mostovi) cout << " " << a << "-" << b;
    cout << endl << "Artikulacioni:";
    for (int v = 1; v <= n; v++) if (artikulacioni[v]) cout << " " << v;
    cout << endl;
    return 0;
}

Složenost je O(n + m) – jedan obilazak. Ovaj program pretpostavlja da između dva čvora postoji najviše jedna grana; ako ih može biti više, umesto roditelja treba preskakati samo granu (po rednom broju) kojom smo došli.

Zadaci za vežbu

Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.

ZADATAK 01Težina: Srednje

Kritični putevi

Mreža puteva između n sela je povezana. Put je kritičan ako bi njegovim zatvaranjem neka sela ostala odsečena. Ispiši broj kritičnih puteva.

Primer 1

Ulaz

6 6
1 2
2 3
1 3
3 4
4 5
5 6

Izlaz

3

Primer 2

Ulaz

3 3
1 2
2 3
3 1

Izlaz

0
Česte greške i saveti
  • U neusmerenom grafu ne koristi granu ka roditelju kao povratnu.
  • Za mostove je uslov low[u] > tin[v], a za artikulacione čvorove low[u] >= tin[v].
  • Koren DFS stabla ima poseban uslov: bar dva deteta.

Proveri znanje

Otvori kviz

Mostovi i artikulacioni čvorovi

1. Šta je most u grafu?




2. Da li grana koja leži na ciklusu može biti most?




3. Kada je koren DFS stabla artikulacioni čvor?