Witam, mam do napisania kod sprawdzający dwudzielność i ilość składowych spójności grafu. I tak właściwie to... zrobiłem to, ale mój kod jest bardzo, bardzo nieefektywny dla dużych grafów (niestety, nie mogę określić jak dużych, sprawdza mi to kochany spoj :)) Mogę liczyć na jakieś wskazówki, jak możnaby zrobić to lepiej? (nie liczę na gotowe rozwiązanie, tylko jakiś pomysł, na który wpaść nie mogę). O spowalnianie kodu podejrzewam rekurencję, ale nie potrafię sobie poradzić bez niej. :(
Starałem się obkomentować kod jak najlepiej, ale jeśli coś jest niejasne to proszę pytać.
Oto mój dotychczasowy kod (troszkę ucięty dla czytelności, ale kluczowe elementy pozostają te same)
#include <cstdlib>
#include <iostream>
#include <vector>
#include <list>
using namespace std;
class Node {
int nr;
public :
Node(int nr) {
this->nr = nr;
}
int & GetNr() {
return nr;
}
};
// funkcja sprawdza dwudzielność grafu, parametrami są graf w postaci wektora list
// aktualnie przetwarzany wierzchołek (powinno się zaczynać od 0), wektor stanu wierzchołków,
// oraz nr. zbioru do którego ma należeć wierzchołek (kolor wierzchołka, 1 lub -1)
bool CheckBipartite(vector <list<Node> > graf, int wierzcholek, vector <int> &wierzcholki, int zbior) {
bool isBipartite = false;
for (list<Node>::iterator current = graf[wierzcholek].begin(); current != graf[wierzcholek].end();) {
int currentNr = wierzcholki[current->GetNr()];
if (currentNr == -zbior) continue; //jesli prawidlowo pokolorowany, pomiń
else if (currentNr == zbior) { //jesli źle, graf nie jest dwudzielny
return isBipartite;
} else if (currentNr == 0) { // jeśli niepokolorowany, nadaj przeciwny kolor i wywołaj funkcję dla sąsiadów
wierzcholki[current->GetNr()] = -zbior;
//sprawdz czy sąsiedzi nie zaalarmowali, że graf nie jest dwudzielny
if (!CheckBipartite(graf, current->GetNr(), wierzcholki, -zbior)) return isBipartite;
}
++current;
}
isBipartite = true;
return isBipartite;
}
//BFS, "odwiedza" wierzchołki
void SetVertexAsVisited(vector <list<Node> > graf, int wierzcholek, vector <int> &wierzcholki) {
if (wierzcholki[wierzcholek] == 0) {
wierzcholki[wierzcholek] = 1;
for (list<Node>::iterator current = graf[wierzcholek].begin(); current != graf[wierzcholek].end();) {
SetVertexAsVisited(graf, current->GetNr(), wierzcholki);
++current;
}
}
}
//funkcja obliczająca ilość składowych spójności
int HowManyCComponents(vector <list<Node> > graf, vector <int> &wierzcholki) {
int ConnectedComponents = 1;
SetVertexAsVisited(graf, 0, wierzcholki); //najpierw dla 1 wierzcholka
for (int i=0; i<wierzcholki.size(); ++i) { //maksymalna ilosc skladowych to size()
if (wierzcholki[i] == 0) { // jesli w tablicy sa jakieś 0
++ConnectedComponents; // znaczy że nie można było dojść do któregos wierzcholka
SetVertexAsVisited(graf, i, wierzcholki); // wniosek, kolejna składowa spojności
}
}
return ConnectedComponents;
}
int main(int argc, char** argv) {
int wierzcholki, krawedzie;
int para1, para2;
bool isError = false;
cin >> wierzcholki >> krawedzie;
//wczytujemy graf nieskierowany do wektora list
vector <list<Node> > graf(wierzcholki);
//odczytujemy krawedzie w grafie
for (int i=0; i < krawedzie; ++i) {
// wczytaj wierzcholki do polaczenia ze sobą
cin >> para1 >> para2;
--para1; //wierzcholki numerowane od 1 do size()!
--para2; //każda operacja wyswietlenia wierzchołków na ekranie
//musi byc poprzedzona dodaniem jedynki
// czy podano wierzcholki ktore nie istnieja w grafie?
if (para1 > wierzcholki || para2 > wierzcholki) {
isError = true;
break;
}
Node a(para2);
Node b(para1);
//wpisz wierzcholki do odpowiednich list
graf[para1].push_back(a);
graf[para2].push_back(b);
}
cout << endl;
if (isError) return (EXIT_FAILURE);
vector <int> vwierzcholki(wierzcholki); //przetrzymuje stan wierzcholkow
//do sprawdzenia spójności grafu
cout << HowManyCComponents(graf, vwierzcholki) << " ";
//zerowanie wektora stanów
vwierzcholki.assign(wierzcholki, 0);
// do sprawdzenia dwudzielności grafu
vwierzcholki[0] = 1; //nr zbioru pierwszego wierzcholka
if (CheckBipartite(graf, 0, vwierzcholki, 1)) cout << "T";
else cout << "N\n";
return (EXIT_SUCCESS);
}