Pagini recente » Cod sursa (job #1620996) | Cod sursa (job #1905537) | Cod sursa (job #1969734) | Cod sursa (job #2944411) | Cod sursa (job #2795970)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_set>
using namespace std;
int nodSursa;
int distante[100001];
vector<unordered_set<int>> componenteBiconexe;
vector<int> vizPasi;
vector<int> nivelMinimIntoarcere;
stack<pair <int, int>> StivaMuchiiComponentaBiconexaCurenta;
vector<vector<int>> ComponenteTareConexe;
stack<int> StivaComponentaTareConexaCurenta;
vector<int> isInStiva;
vector<int> arrivalTime;
vector<int> lowLinkValue;
int arrivalTimeCurent;
class Graf {
private:
int m_nrNoduri;
vector<vector<int>> m_listAdiacenta;
vector<int> viz;
public:
void citire(){
ifstream f("../ctc.in");
vector<int> aux;
int nrMuchii;
f>>this->m_nrNoduri;
this->m_listAdiacenta.assign(this->m_nrNoduri + 1, aux);
f>>nrMuchii;
for(int i=0; i<nrMuchii; i++){
int x,y;
f>>x>>y;
this->m_listAdiacenta[x].push_back(y);
}
viz.assign(this->m_nrNoduri + 1, 0);
}
void prelucrare(int nod, int x){
//cout<<nod<<"\n";
distante[nod] = distante[x] + 1;
}
void BFS(int nod){
int curent;
queue<int> coada;
int viz[this->m_nrNoduri+1];
for(int i=1; i<=m_nrNoduri; i++){
viz[i] = 0;
}
coada.push(nod);
viz[nod] = 1;
prelucrare(nod, nod);
while(!coada.empty()){
curent = coada.front();
for(int i=0; i < this->m_listAdiacenta[curent].size(); i++){
if(viz[this->m_listAdiacenta[curent][i]] == 0){
coada.push(this->m_listAdiacenta[curent][i]);
prelucrare(coada.back(),curent);
viz[this->m_listAdiacenta[curent][i]] = 1;
}
}
coada.pop();
}
}
/*
void prelucrareDFS(int nod){
cout<<nod<<endl;
}
*/
void DFS(int nod){
//prelucrareDFS(nod);
viz[nod] = 1;
for(int i=0; i<this->m_listAdiacenta[nod].size(); i++){
if(viz[this->m_listAdiacenta[nod][i]] == 0){
DFS(this->m_listAdiacenta[nod][i]);
}
}
}
void afisDrumuri() {
ofstream g("../bfs.out");
for(int i=1; i <= this->m_nrNoduri; i++){
g<<distante[i] - 1<<" ";
}
}
void DFSBiconexe(int nodCurent, int precedent, int pas){
//marcam ca vizitat nodul curent
vizPasi[nodCurent] = pas;
//momentan nivelul minim de intoarcere e nivelul curent, adica pasul
nivelMinimIntoarcere[nodCurent] = pas;
//parcurgem vecinii nodului curent
for(int i=0; i<this->m_listAdiacenta[nodCurent].size(); i++){
int vecinCurent = this->m_listAdiacenta[nodCurent][i];
if(vecinCurent != precedent){
//verificam pe ce fel de muchie suntem
//daca vecinul curent a mai fost vizitat inseamna ca am dat de o muchie de intoarcere, altfel suntem pe o muchie in jos
if(vizPasi[vecinCurent] == -1){
//am dat de o noua muchie din componenta biconexa curenta, asa ca o adaugam in stiva
StivaMuchiiComponentaBiconexaCurenta.push(make_pair(nodCurent, vecinCurent));
//apelam DFS pentru vecinul curent
DFSBiconexe(vecinCurent, nodCurent, pas + 1);
//verificam daca atunci cand ne am dus mai departe in graf
// am dat de o muchie de intoarcere care ne duce mai sus decat ne ducea nodul acesta inainte
if(nivelMinimIntoarcere[nodCurent] > nivelMinimIntoarcere[vecinCurent]){
nivelMinimIntoarcere[nodCurent] = nivelMinimIntoarcere[vecinCurent];
}
//verificam daca am ajuns la finalul componentei biconexe
if(nivelMinimIntoarcere[vecinCurent] >= vizPasi[nodCurent]){
//trebuie sa adaugam noua componenta biconexa in vectorul de componenete biconexe
//si sa golim stiva cu muchiile componentei biconexe curente
unordered_set<int> aux;
int aux1, aux2;
do{
aux1 = StivaMuchiiComponentaBiconexaCurenta.top().first;
aux2 = StivaMuchiiComponentaBiconexaCurenta.top().second;
aux.insert(aux1);
aux.insert(aux2);
StivaMuchiiComponentaBiconexaCurenta.pop();
} while (aux1 != nodCurent || aux2 != vecinCurent);
componenteBiconexe.push_back(aux);
}
}else{
//avem o muchie de intoarcere, trebuie sa verificam daca nu cumva duce mai sus
if(nivelMinimIntoarcere[nodCurent] > vizPasi[vecinCurent]){
nivelMinimIntoarcere[nodCurent] = vizPasi[vecinCurent];
}
}
}
}
}
void afisComponenteBiconexe(){
ofstream g("../biconex.out");
vizPasi.assign(this->m_nrNoduri + 1, -1);
nivelMinimIntoarcere.resize(this->m_nrNoduri + 1);
DFSBiconexe(1,0,0);
g<<componenteBiconexe.size()<<"\n";
for(int i=0; i<componenteBiconexe.size(); i++){
for(unordered_set<int>::iterator it = componenteBiconexe[i].begin(); it != componenteBiconexe[i].end(); it++){
g<<*it<<" ";
}
g<<"\n";
}
}
void tarjan(int nod){
//adaugam nodul in componenta tare conexa curenta, adica in StivaComponentaTareConexaCurenta
StivaComponentaTareConexaCurenta.push(nod);
//marcam nodul ca facand parte din componenta tare conexa curenta prin vectorul isInStiva
isInStiva[nod] = 1;
//marcam nodul ca vizitat, atribuindu-i chiar timpul de ajungere
arrivalTime[nod] = arrivalTimeCurent;
//valoarea low Link momentan este tot nivelul nodului curent
lowLinkValue[nod] = arrivalTimeCurent;
//marim timpul de ajungere pentru urmatorul pas
arrivalTimeCurent++;
//parcurgem vecinii nodului curent, facand un DFS
for(int i=0; i<this->m_listAdiacenta[nod].size(); i++){
int vecinCurent = this->m_listAdiacenta[nod][i];
//verificam daca vecinul curent nu a fost inca vizitat
if(arrivalTime[vecinCurent] == -1){
//aplicam tarjan pe nodul curent
tarjan(vecinCurent);
//la iesire incercam sa minimizam valoarea low link a nodului curent, daca vecinul la care suntem a facut in timpul tarjan-ului una mai mica
if(lowLinkValue[vecinCurent] < lowLinkValue[nod]){
lowLinkValue[nod] = lowLinkValue[vecinCurent];
}
}else{ //daca vecinul a fost deja vizitat
//verificam daca vizitarea s-a produs in cadrul componentei tare conexe curente
if(isInStiva[vecinCurent] == 1){
//incercam sa minimizam valoarea low link a nodului curent, in cazul in care vecinul curent ajunge la un nod mai indepartat decat valoarea noastra curenta
if(lowLinkValue[vecinCurent] < lowLinkValue[nod]){
lowLinkValue[nod] = lowLinkValue[vecinCurent];
}
}
}
}
//verificam daca nodul curent inchide o componenta tare conexa
if(arrivalTime[nod] == lowLinkValue[nod]){
//trebuie sa mutam componenta tare conexa curenta din stiva in vectorul cu toate componentele tare conexe din graf
vector<int> aux;
int nodAux;
do{
nodAux = StivaComponentaTareConexaCurenta.top();
aux.push_back(nodAux);
StivaComponentaTareConexaCurenta.pop();
isInStiva[nodAux] = 0;
}while(nodAux != nod);
ComponenteTareConexe.push_back(aux);
}
}
void afisComponenteTareConexe(){
ofstream g("../ctc.out");
g<<ComponenteTareConexe.size()<<"\n";
for(int i=0; i<ComponenteTareConexe.size(); i++){
for(int j=0; j<ComponenteTareConexe[i].size(); j++){
g<<ComponenteTareConexe[i][j]<<" ";
}
g<<"\n";
}
}
void numaraComponenteTareConexe(){
isInStiva.assign(this->m_nrNoduri + 1, 0);
arrivalTime.assign(this->m_nrNoduri + 1, -1);
lowLinkValue.resize(this->m_nrNoduri + 1);
for(int i=1; i<=this->m_nrNoduri; i++){
if(arrivalTime[i] == -1){
tarjan(i);
}
}
afisComponenteTareConexe();
}
};
int main() {
ofstream out("../biconex.out");
Graf g;
g.citire();
g.numaraComponenteTareConexe();
return 0;
}