U gradu postoji \(n\) raskrsnica povezanih jednosmernim i dvosmernim ulicama. Kako je grad moderan, neke od ulica imaju nadvožnjake. Potrebno je obezbediti da svake dve raskrsnice budu povezane. Preciznije, za svake dve raskrsnice \(v\) i \(w\) mora da važi da je iz \(v\) moguće doći u \(w\) i da je iz \(w\) moguće doći u \(v\). Potrebno je napisati program koji učitava opise puteva u gradovima i ispisuje za koje gradove je zadovoljen uslov povezanosti.
Sa standardnog ulaza se učitava broj upita \(q\), a zatim i sami upiti. Svaki upit ima u prvoj liniji dva cela broja \(n\) i \(m\) (\(1 \leq n \leq 100\)), koji redom predstavljaju broj raskrsnica i broj ulica u datom gradu. Nakon toga se u sledećih \(m\) linija zadaju ulice na sledeći način:
Na standardni izlaz za svaki od upita ispisati Da
ukoliko je uslov povezanosti svaka dva čvora ispunjen, a Ne
u suprotnom.
4 4 5 1 1 2 2 1 3 1 2 4 1 3 4 2 4 1 3 2 2 1 2 2 1 3 3 2 2 1 2 1 1 3 4 2 2 1 2 2 3 4
Da Da Ne Ne
Zadatak se svodi na proveru da li je graf jako povezan. Koristimo Kosarajuov algoritam koji se oslanja na činjenicu da ukoliko obrnemo grane u grafu, sastav komponenti jake povezanosti ostaje isti. Sastoji se iz sledećih koraka:
Pokrenuti DFS iz proizvoljnog početnog čvora. Ukoliko nakon toga postoji neki neposećen čvor, zaključujemo da graf nije jako povezan, pošto taj čvor i početni čvor ne mogu biti u istoj komponenti.
Pokrenuti ponovo DFS iz istog početnog čvora, ali za graf sa obrnutim granama. Ukoliko sada postoji neki neposećen čvor, ponovo taj čvor i početni čvor ne mogu biti u istoj komponenti na osnovu pretpostavke algoritma, pa zaključujemo da graf nije jako povezan. U suprotnom graf jeste jako povezan.
#include <iostream>
#include <vector>
#include <utility>
#include <stack>
#include <algorithm>
using namespace std;
class Graph {
private:
int broj_cvorova;
int>> lista_suseda;
vector<vector<int>> obrnuta_lista_suseda;
vector<vector<bool> posecen;
vector<
public:
int broj_cvorova) {
Graph(this->broj_cvorova = broj_cvorova;
lista_suseda.resize(broj_cvorova);
obrnuta_lista_suseda.resize(broj_cvorova);false);
posecen.resize(broj_cvorova,
}
void dodaj_granu(bool usmerena, int u, int v) {
lista_suseda[u].push_back(v);
obrnuta_lista_suseda[v].push_back(u);if(!usmerena){
lista_suseda[v].push_back(u);
obrnuta_lista_suseda[u].push_back(v);
}
}
void dfs1(int koren) {
int> s;
stack<
s.push(koren);true;
posecen[koren] =
int trenutni;
while (!s.empty()) {
trenutni = s.top();
s.pop();
for (int neighbour : lista_suseda[trenutni])
if (!posecen[neighbour]) {
s.push(neighbour);true;
posecen[neighbour] =
}
}
}
void dfs2(int koren) {
int> s;
stack<
s.push(koren);true;
posecen[koren] =
int trenutni;
while (!s.empty()) {
trenutni = s.top();
s.pop();
for (int neighbour : obrnuta_lista_suseda[trenutni])
if (!posecen[neighbour]) {
s.push(neighbour);true;
posecen[neighbour] =
}
}
}
bool kosaraju(int koren){
dfs1(koren);
for(int i = 0; i < broj_cvorova; i++)
if(posecen[i] == false)
return false;
false);
fill(posecen.begin(), posecen.end(),
dfs2(koren);
for(int i = 0; i < broj_cvorova; i++)
if(posecen[i] == false)
return false;
return true;
}
};
int main() {
int q;
cin >> q;
while(q--){
int broj_cvorova, number_of_edges;
cin >> broj_cvorova >> number_of_edges;
new Graph(broj_cvorova);
Graph *G =
int u, v, je_usmeren;
for (int i = 0; i < number_of_edges; i++) {
cin >> je_usmeren >> u >> v;if(je_usmeren == 1)
true, u-1, v-1);
G->dodaj_granu(else
false, u-1, v-1);
G->dodaj_granu(
}
if(G->kosaraju(0))
"Da" << endl;
cout << else
"Ne" << endl;
cout <<
delete G;
}return 0;
}