Pagini recente » Cod sursa (job #286490) | Cod sursa (job #899015) | Cod sursa (job #1839777) | Cod sursa (job #769713) | Cod sursa (job #2796607)
#include <bits/stdc++.h>
#define NMax 100001
using namespace std;
ifstream fin("biconex.in");
ofstream fout("biconex.out");
// DFS
bool vizDFS[NMax];
// Kosaraju
stack <int> S; // stiva pentru memorarea nodurilor in ordinea timpilor de final
bool vizDFST[NMax]; // pt graful transpus
vector <int> grT[NMax]; // liste de adiacenta ale grafului transpus
vector <int> componente[NMax]; // liste cu nodurile care compun fiecare componenta tare conexa in parte
// Havel-Hakimi
vector <int> grade;
// Muchii Critice + Comp Biconexe
bool vizDFSC[NMax];
int nivel[NMax]; // nivelul pe care se gaseste nodul
int niv_min_acc[NMax]; // nivelul minim accesibil
int ct_muchii_critice;
vector <vector<int>> muchii_critice;
// Biconex
int ct_biconexe;
stack <int> S2;
vector <int> componente_biconexe[NMax];
class graf
{
int nrNoduri, nrMuchii;
bool orientat;
vector <int> gr[NMax]; // liste de adiacenta ale grafului
public:
graf(int n, int m, bool o); // constructor
void Citire_Orientat();
void Citire_Neorientat();
void Afisare_Graf();
void BFS(int s); // s - nodul de start
void DFS(int s); // s - nodul de start
// Determinare nr de componente conexe
void Comp_Conexe(); // afiseaza cate componente conexe are graful
// Kosaraju
void Graf_Transpus(); // creeaza graful transpus in grT
void ParcurgereGrafInitial(); // parcurgerea in adancime a grafului initial
void DFST(int s, int culoare); // s - nodul de start, dfs pe graful transpus
void CTC(); // apeleasa DFST si afiseaza comp tare conexe
// Sortare topologica
void Sortare_Topologica();
// Algoritm Havel-Hakimi
bool Havel_Hakimi(vector<int>grade, int nrNoduri);
// Afisare Muchii Critice
void Muchii_Critice();
void DFS_Critice(int s, int tata);
// Afisare Componente Biconexe
void DFS_Biconex(int s, int tata);
void Componente_Biconexe();
};
graf :: graf(int n, int m, bool o)
{
nrNoduri = n;
nrMuchii = m;
orientat = o;
}
void graf :: Citire_Orientat()
{
for(int i = 1; i <= nrMuchii; ++i)
{
int x, y;
fin >> x >> y;
gr[x].push_back(y);
}
}
void graf :: Citire_Neorientat()
{
for(int i = 1; i <= nrMuchii; ++i)
{
int x, y;
fin >> x >> y;
gr[x].push_back(y);
gr[y].push_back(x);
}
}
void graf :: Graf_Transpus()
{
for(int i = 1; i <= nrNoduri; ++i)
for(auto j : gr[i])
grT[j].push_back(i);
}
void graf :: Afisare_Graf()
{
for(int i=1; i <= nrNoduri; ++i)
{
fout << i << " : " ;
for(auto j: gr[i])
fout << j << " ";
fout << "\n";
}
}
void graf :: BFS(int s)
{
bool viz[NMax] = {0};
int distanta[NMax] = {0};
queue <int> q;
viz[s] = 1;
q.push(s);
while(!q.empty())
{
int k = q.front(); // elem din varful cozii
q.pop(); // sterg elem din varful cozii
for(auto i : gr[k])
if(!viz[i])
{
viz[i] = 1;
q.push(i);
distanta[i] = distanta[k] + 1;
}
}
for(int i = 1; i <= nrNoduri; ++i)
if(viz[i])
fout << distanta[i] << " ";
else
fout << -1 << " ";
}
void graf :: DFS(int s)
{
vizDFS[s] = 1;
for(auto i : gr[s])
if(!vizDFS[i])
DFS(i);
// pentru CTC(Kosaraju) - stabilim timpul de finalizare pentru nodul s
S.push(s);
}
void graf :: Comp_Conexe()
{
int ct = 0;
for(int i = 1; i <= nrNoduri; ++i)
if(!vizDFS[i])
{
ct++;
DFS(i);
}
fout << ct;
}
void graf :: ParcurgereGrafInitial()
{
for(int i = 1; i <= nrNoduri; ++i)
if(!vizDFS[i])
DFS(i);
}
void graf :: DFST(int s, int ct)
{
vizDFST[s] = 1;
componente[ct].push_back(s);
for(auto i : grT[s])
if(!vizDFST[i])
DFST(i, ct);
}
void graf :: CTC()
{
int ct_ctc = 0;
while(!S.empty())
{
int varf = S.top();
S.pop();
if(!vizDFST[varf])
{
ct_ctc ++;
DFST(varf, ct_ctc);
}
}
fout << ct_ctc << "\n";
for(int i = 1; i <= ct_ctc; ++i)
{
for(auto j:componente[i])
fout << j << " ";
fout << "\n";
}
}
void graf :: Sortare_Topologica()
{
ParcurgereGrafInitial();
while(!S.empty())
{
fout << S.top() << " ";
S.pop();
}
}
bool myfunction(int i, int j)
{
return (i>j);
}
bool graf :: Havel_Hakimi(vector <int> grade, int nrNoduri)
{
bool ok =1;
while(ok)
{
sort(grade.begin(), grade.end(), myfunction);
if(grade[0] == 0) // daca cel mai mare element dupa sortare este 0 => toate elementele sunt 0 => se poate forma
return true;
if(grade[0] > grade.size() - 1) // daca gradul este mai mare decat nr de noduri curente - 1 => NU se poate forma
return false;
int grad_curent = grade[0];
grade.erase(grade.begin() + 0); // elimin primul element
for(int i = 0; i < grad_curent; ++i) // scad 1 doar din primele grad_curent elemente
{
grade[i] --;
if(grade[i] < 0)
return false;
}
}
}
void graf :: DFS_Critice(int s, int tata)
{
vizDFSC[s] = 1;
nivel[s] = nivel[tata] + 1;
niv_min_acc[s] = nivel[s];
for(auto i : gr[s])
if(i != tata)
{
if(vizDFSC[i] == 1)
{
if(niv_min_acc[s] > nivel[i])
niv_min_acc[s] = nivel[i];
}
else
{
DFS_Critice(i,s);
if(niv_min_acc[s] > niv_min_acc[i])
niv_min_acc[s] = niv_min_acc[i];
}
// determinare muchii critice
if(nivel[s] < niv_min_acc[i])
{
// (s, i)
ct_muchii_critice++;
vector <int> v1;
v1.push_back(s);
v1.push_back(i);
muchii_critice.push_back(v1);
}
}
}
void graf :: Muchii_Critice()
{
DFS_Critice(1,0);
fout << ct_muchii_critice << "\n";
for( vector<vector<int>>::iterator i = muchii_critice.begin() ; i != muchii_critice.end(); i++ )
{
fout << "[" ;
vector<int>::iterator j = i->begin();
fout<<*j;
fout << ",";
j++;
fout <<*j;
fout << "] ";
}
}
void graf :: DFS_Biconex(int s, int tata)
{
vizDFSC[s] = 1;
S2.push(s);
nivel[s] = nivel[tata] + 1;
niv_min_acc[s] = nivel[s];
for (auto i : gr[s])
{
if (vizDFSC[i] == 1)
{
if(niv_min_acc[s] > nivel[i])
niv_min_acc[s] = nivel[i];
}
else
{
DFS_Biconex(i, s);
if(niv_min_acc[s] > niv_min_acc[i])
niv_min_acc[s] = niv_min_acc[i];
// determinare componente biconexe
if(niv_min_acc[i] >= nivel[s])
{
ct_biconexe ++;
/*
while(!S2.empty() && S2.top() != i)
{
componente_biconexe[ct_biconexe].push_back(S2.top());
S2.pop();
}
componente_biconexe[ct_biconexe].push_back(S2.top());
S2.pop();
componente_biconexe[ct_biconexe].push_back(s);
*/
}
}
}
}
void graf :: Componente_Biconexe()
{
DFS_Biconex(1,0);
fout << ct_biconexe << "\n";
/*
for(int i = 1; i <= ct_biconexe; ++i)
{
for(auto j : componente_biconexe[i])
fout << j << " ";
fout << "\n";
}
*/
}
int N, M;
int main()
{
fin >> N >> M;
graf G(N, M, 0);
G.Citire_Neorientat();
G.Componente_Biconexe();
return 0;
}