Cod sursa(job #7757)

Utilizator stef2nStefan Istrate stef2n Data 22 ianuarie 2007 16:15:15
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.11 kb
#include <stdio.h>
#include <stdlib.h>

#define infile "radiatie.in"
#define outfile "radiatie.out"
#define NMAX 15005
#define MCHMAX 30005
struct muchie{int u,v,c;};
struct NOD{int x,c; struct NOD *adr;};

FILE *fin,*fout;
int n,m,k;
muchie mch[MCHMAX];
char used[MCHMAX];
int precarb[NMAX];
NOD *prim[NMAX];
char vizitat[NMAX];
int prec[NMAX],niv[NMAX],cost[NMAX];
int stramos[15][NMAX],radiatie[15][NMAX];

inline int cmp(const void *ma, const void *mb)
  {
   muchie a=*((muchie *)ma);
   muchie b=*((muchie *)mb);
   return -(a.c<b.c)+(a.c>b.c);
  }

inline void adaug_st(NOD *(&prim), int x, int c)
  {
   NOD *a=new NOD;
   a->x=x;
   a->c=c;
   a->adr=prim;
   prim=a;
  }

int root(int u)
  {
   if(precarb[u]<0)
     return u;
   return root(precarb[u]);
  }

inline void uneste(int rad1, int rad2)
  {
   if(precarb[rad1]<precarb[rad2]) // adica rad1 are adancime mai mare decat rad2
     precarb[rad2]=rad1;
   else
     if(precarb[rad1]>precarb[rad2]) // adica rad2 are adancime mai mare decat rad1
       precarb[rad1]=rad2;
     else // rad1 si rad2 au aceleasi adancimi
       {
        precarb[rad1]=rad2;
        precarb[rad2]--;
       }
  }

inline int max(int x, int y)
  {
   return (x>y)?x:y;
  }

void df(int varf, int nivel)
  {
   NOD *b=prim[varf];
   while(b)
      {
       if(!vizitat[b->x])
         {
          vizitat[b->x]=1;
          prec[b->x]=varf;
          niv[b->x]=nivel+1;
          cost[b->x]=b->c;
          df(b->x,nivel+1);
         }
       b=b->adr;
      }
  }

inline int poz_2(int x)
  {
   if(x>>1)
     return poz_2(x>>1)+1;
   else
     return 1;
  }

void cauta_stramos(int n, int varf, int &tata, int &rad)
  {
   int rang,rang_ini;
   tata=varf;
   rad=0;
   while(n)
        {
         rang_ini=rang=n^(n&(n-1));
         rang=poz_2(rang);
         rad=max(rad,radiatie[rang-1][tata]);
         tata=stramos[rang-1][tata];
         n-=rang_ini;
        }
  }

int interogare(int u, int v)
  {
   int maxim=0,maxim2=0,i,gasit=0;

   if(niv[u]>niv[v])
     cauta_stramos(niv[u]-niv[v],u,u,maxim);
   if(niv[v]>niv[u])
     cauta_stramos(niv[v]-niv[u],v,v,maxim2);
   maxim=max(maxim,maxim2);
   if(u==v)
     return maxim;

   i=0;
   while(i<=14 && !gasit)
        if(stramos[i][u]==stramos[i][v])
          gasit=1;
        else
          i++;
   if(!i)
     {
      maxim=max(maxim,radiatie[i][u]);
      maxim=max(maxim,radiatie[i][v]);
      return maxim;
     }
   i--;
   maxim=max(maxim,radiatie[i][u]);
   maxim=max(maxim,radiatie[i][v]);
   maxim=max(maxim,interogare(stramos[i][u],stramos[i][v]));

   return maxim;
  }


int main()
{
int i,j;
fin=fopen(infile,"r");
fout=fopen(outfile,"w");
fscanf(fin,"%d %d %d",&n,&m,&k);
for(i=0;i<m;i++)
   {
    fscanf(fin,"%d %d %d",&mch[i].u,&mch[i].v,&mch[i].c);
    mch[i].u--;
    mch[i].v--;
   }
qsort(mch,m,sizeof(muchie),cmp);

// Kruskal
for(i=0;i<m;i++)
   used[i]=0;
for(i=0;i<n;i++)
   precarb[i]=-1;
int ru,rv;
for(i=0;i<m;i++)
  {
   ru=root(mch[i].u);
   rv=root(mch[i].v);
   if(ru!=rv)
     {
      uneste(ru,rv);
      used[i]=1;
     }
  }

// construire arbore
for(i=0;i<n;i++)
   prim[i]=NULL;
for(i=0;i<m;i++)
   if(used[i])
     {
      adaug_st(prim[mch[i].u],mch[i].v,mch[i].c);
      adaug_st(prim[mch[i].v],mch[i].u,mch[i].c);
     }

for(i=0;i<n;i++)
   vizitat[i]=0;
for(i=0;i<n;i++)
   if(!vizitat[i])
     {
      vizitat[i]=1;
      prec[i]=-1;
      niv[i]=0;
      df(i,0);
     }

// preprocesare stramosi => se calculeaza, pentru fiecare varf, stramosii de ordin 2^k si radiatia pana la ele
for(j=0;j<n;j++)
   {
    stramos[0][j]=prec[j];
    if(prec[j]==-1)
      radiatie[0][j]=-1;
    else
      radiatie[0][j]=cost[j];
   }
for(i=1;i<=14;i++)
   for(j=0;j<n;j++)
      if(stramos[i-1][j]==-1)
        stramos[i][j]=radiatie[i][j]=-1;
      else
        {
         stramos[i][j]=stramos[i-1][stramos[i-1][j]];
         if(stramos[i][j]==-1)
           radiatie[i][j]=-1;
         else
           radiatie[i][j]=max(radiatie[i-1][j],radiatie[i-1][stramos[i-1][j]]);
        }

// rezolvarea interogarilor
int u,v;
for(i=0;i<k;i++)
  {
   fscanf(fin,"%d %d",&u,&v);
   u--;v--;
   fprintf(fout,"%d\n",interogare(u,v));
  }

fclose(fin);
fclose(fout);
return 0;
}