Pagini recente » Cod sursa (job #2177047) | Cod sursa (job #2741339) | Cod sursa (job #2881140) | Cod sursa (job #1885105) | Cod sursa (job #1858251)
/*
graful va fi memorat cu listele de adiacenta retinute de o matrice
pentru a identifica componentele biconexe, vom folosi un vector care retine muchiile grafului(indiferent daca fac parte din dfs
sau sunt muchii de intoarcere) in ordinea parcurgerii dfs. Cand identificam un punct de articulatie,
eliminam din vector toate muchiile din componenta biconexa respectiva si le copiem intr o matrice bi ce va retine
toate componentele biconexe
Variabila cate retine numarul de componente biconexe, iar varf retine indicele varfului stivi
Consider pentru simplitate nodul 1 ca fiind de start in dfs
*/
#include <fstream>
#include<vector>
#include<algorithm>
#define dim 200005
using namespace std;
struct muchie
{
int fiu, tata;
};
muchie S[dim];
vector<int>a[dim];
vector<vector <int> >bi;
int ord[dim],lowLink[dim],cate,nrOrd,varf;
int n,m;
void citire()
{
int i,j,k,x,y;
ifstream fin("biconex.in");
fin>>n>>m;
for(k=1;k<=m;k++)
{
fin>>x>>y;
a[x].push_back(y);
a[y].push_back(x);
}
fin.close();
}
void dfs(int nodCurr, int nodTata)
{
//nodCurr este nodul curent, iar nodTata este nodul lui parinte
int i,nod,x,y;
muchie h;
//cand se ajunge aici crestem numarul de ordine din dfs si il atribuim si lui ord si lui lowLink
nrOrd++;
ord[nodCurr]=lowLink[nodCurr]=nrOrd;
//i este variabila de parcurgere a listei unui nod
//nod este nodul adiacent lui nodCurr
//parcurg lista de adiacenta a nodului nodCurr
for(i=0;i<a[nodCurr].size();i++)
{
nod=a[nodCurr][i];
//daca`nodul este chiar parintele nu ne intereseaza
if(nod==nodTata)
continue;
//daca nod nu a mai fost vizitat
if(ord[nod]==-1)
{
//introduc in S muchia (nod,nodCurr)
h.tata=nodCurr;
h.fiu=nod;
varf++;S[varf]=h;
//reapelez functia pentru nod si nodCurr care va deveni nodTata
dfs(nod,nodCurr);
//la derecursivitate
//calculez minimul dintre lowLink de extremitatile muchiei nodCurr, nod
lowLink[nodCurr]=min(lowLink[nodCurr],lowLink[nod]);
//daca nodCurr este punct de articulatie, am gasit o componenta biconexa
//formata din toate muchiile stivei pana la intalnirea muchiei [nodCurr,nod]
if(lowLink[nod]>=ord[nodCurr])
{
cate++;
//copii in matricea bi, componenta conexa din stiva
//vectorul aux retine acea componenta luata din S
vector<int>aux;
do
{
x=S[varf].fiu;
y=S[varf].tata;
varf--;
aux.push_back(x);
aux.push_back(y);
}
while(y!=nodCurr || x!=nod);
bi.push_back(aux);
}
}
else
{
//in acez caz nodCurr a mai fost vizitat, verific daca este o muchie de intoarcere si actualizez lowLink
if(nodCurr!=nodTata)
lowLink[nodCurr]=min(lowLink[nodCurr],ord[nod]);
}
}
}
int main()
{
ofstream fout("biconex.out");
citire();
int i,j;
for(i=1;i<=n;i++)
ord[i]=lowLink[i]=-1;
//initializez vectorul S cu nodul de pornire, el nu are tata, consider -1
S[0].fiu=1;
S[0].tata=-1;
dfs(1,0);
fout<<cate<<"\n";
//afisez fiecare linie a lui bi
for(i=0;i<bi.size();i++)
{
//in fiecare linie unele noduri apar de mai multe ori si sunt in ordine inversa
//sortez si elimim duplicatele
sort(bi[i].begin(), bi[i].end());
bi[i].erase(unique(bi[i].begin(), bi[i].end()), bi[i].end());
for(j=0;j<bi[i].size();j++)
fout<<bi[i][j]<<" ";
fout<<"\n";
}
return 0;
}