Cod sursa(job #287540)

Utilizator conttPop Mircea contt Data 24 martie 2009 22:31:38
Problema Componente biconexe Scor 40
Compilator cpp Status done
Runda aa Marime 4.77 kb
 #include <fstream.h>  
 #define nmax 100005  
 #define nmax2 200005  
  
   ifstream f("biconex.in");  
    ofstream g("biconex.out");  
      
   struct lista {long nod; lista *urm;};  
   struct l2{long x, y; l2 *urm,*prec;}; //lista dublu inlantuita
   //prec pointer spre nodul precedent
   //urm pointer spre nodul urmator
   
   
  long n,m,tata[nmax],l[nmax],nivel[nmax],nr;  
  lista *a[nmax2];  
  l2 *s, *sol[nmax2];  
 
 
 //******************LISTELE DE VECINI 
   
 //pun y in lista de vecini a lui x
 void adaug_vecin(long x, long y)  
   {lista *p;  
    
     p=new lista;  
     p->nod=y;  
     p->urm=NULL;  

    if (a[x])  
       p->urm=a[x];  
     
     a[x]=p;  
   }  

//************************CONSTRUIREA SOLUTIEI  sol[nr]=inceputul unei liste care retine solutia nr

//adaug la solutie muchia (x,y)
void adaug_sol(long x, long y)  
{l2 *d;  
  
   d=new l2;  
   d->x=x;  
   d->y=y;  
   
   d->urm=0;  
   d->prec=0;  
  
  if(sol[nr]!=0)  
   {d->prec=sol[nr];  
    sol[nr]->urm=d;  
   }  
    
  sol[nr]=d;  
  }  
   
//************************ELIMINAM O MUCHIE DIN STIVA S 

//!!!!!!!!!!!!!!!!!!!!!!TRANSIMTEM CE AM ELIMINAT(VALOAREA LUI X SI Y)!!!!!!!!!!!! 
 //elimin muchia (x,y) din stiva  
void elimin(long *x, long *y)  
{l2 *d;  
  
 d=new l2;  
   
 *x=s->x;  
 *y=s->y;  
 
  d=s;  
  
  s=s->prec;  
  delete d;  
 }  
  


//**************************ADAUGAM ELEMENTE IN STIVA S

void adaug_stiva(long x, long y)  
 {l2 *d;  
   d=new l2;  
    
     d->x=x;  
     d->y=y;  
     d->urm=NULL;//ambii pointeri (campuri de legatura)
     d->prec=NULL;  //ii initializez cu NULL
 
    //adaug nodul d
    if(s!=0)  //daca s nu are elemente se va executa doar atribuirea s=d
     {d->prec=s;  
      s->urm=d;  
    }  
   
  

   s=d;  
  }  
  
  
//*********************PARCURGEREA IN ADANCIME


//parcurgerea in adancime   
void df(long k)  
{lista *p;  
 l2 *d;  
 long x,y;  
   
   l[k]=nivel[k];//initializez nivelul de care pot ajunge de la nodul k
              //chiar cu nivelul pe care se afla in cazul parcurgerii df  
    
for (p=a[k];p!=0;p=p->urm)  //parcurg lista de vecini a lui k
                             //  am declarat : "lista *a[nmax2];"
                            
    if (!tata[p->nod])  //daca nu este adaugat deja
       {adaug_stiva(k,p->nod);  
        tata[p->nod]=k;                  
        nivel[p->nod]=nivel[k]+1;  
    
        df(p->nod);  // functia se va autoapela fara a trece mai departe
     
    //!!!!!!!!!!!!!!!instructiunile de mai jos se vor executa dar doar dupa ce se termina
    //apelurile recursive df(p->nod) deci practic dupa ce sunt construiti vectorii: l,nivel,tata!!!!!!!
  
        if (l[p->nod]<l[k]) l[k]=l[p->nod];//actualizez nivelul pe care pot ajunge din nodul k
                                         
   
        if (l[p->nod]>=nivel[k])  //daca din p->nod nu pot ajunge mai sus de k
          {nr++;                 //am gasit o comp biconexa
      do  
      {elimin(&x,&y); //elimin muchie (x si y) vor primi valori din functia elimin (ult element din stiva s)
       adaug_sol(x,y);//adaug muchia la solutie
       }  
       //pana cand stiva este goala sau am ajuns la muchia (k,p->nod)
      while (s && (x!=k || y!=p->nod) && (x!=p->nod || y!=k));  
      }  
   }  
     else  
      if (p->nod!=tata[k] && nivel[p->nod]<l[k]) //daca p->nod nu este taticul lui k 
              l[k]=nivel[p->nod];         //si nivelul  lui p->nod in cadrul parcurgeri df este mai mic decat nivelul pe
                                        //care pot ajunge de la k atunci actualizez nivelul pe care pot ajunge de la k cu 
                                        //nivelul lui p->nod in cazul parcurgerii df 
         
    
  }  

   
   
 ///**********main 
 
 int main()  
{long i,p1,p2,x,y;  
 f>>n>>m;  //citirea din fisier si adaugarea muchiilor
 for (i=1;i<=m;i++)  
 {f>>p1>>p2;  
  adaug_vecin(p1,p2);  
  adaug_vecin(p2,p1);  
  }  
   
 //apelez parcurgerea in adancime df pentru fiecare nod
 //daca graful este conex atunci df se apeleaza o singura data
 //daca nu este conex se apeleaza pt fiecare componenta conexa  
 for (i=1;i<=n;i++)  
  if (!tata[i])  
   {tata[i]=-1;  
    nivel[i]=1;  
    df(i);  
    }  
  
   
   
 g<<nr<<'\n';  
   
 memset(tata,0,sizeof(tata));  
   //avem nr componente biconexe
 for (i=1;i<=nr;i++)  
 {  
   do  
   {y=sol[i]->y;  
    x=sol[i]->x;  
   
    //if (tata[x]!=i)  
    {g<<x<<" ";  
     //tata[x]=i;  
     }  
   
     //if (tata[y]!=i)  
     {g<<y<<" ";  
      //tata[y]=i;  
     }  
   
     sol[i]=sol[i]->prec;  
    }  
     while (sol[i]);  
  g<<'\n';  
 }  
   
   
 g.close();  
 return 0;  
 }