Cod sursa(job #256182)

Utilizator FlorianFlorian Marcu Florian Data 11 februarie 2009 12:23:21
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.02 kb
#include<stdio.h>
#include<string.h>
#define Inf 0x3f3f3f3f
#define Nmax 15003
FILE*f=fopen("radiatie.in","r");
FILE*g=fopen("radiatie.out","w");
int H[Nmax],N; // H[i] - nodul aflat pe pozitia i in heap
int poz[Nmax]; // poz[i] - pozitia in heap a nodului i
int c[Nmax]; // c[i] - costul nodului i
int viz[Nmax];
int Nod[Nmax]; // Nod[i] - nodul de la care vine elementul de pe pozitia i
int n,m;
int nr,K;
struct Graf{int vf,cst; Graf *urm;};
Graf *G[Nmax];
inline int min(int x, int y)
 {
  if(x>y) return y;
  else return x;
 }
inline void add(int x, int y, int cst)
 {
 Graf *q;
 q=new Graf;
 q->vf = y;
 q->cst = cst;
 q->urm = G[x];
 G[x]=q;
 }
void read()
 {
  fscanf(f,"%d%d%d",&n,&m,&K);
  int a,b,c;
  while(m--)
   {
    fscanf(f,"%d%d%d",&a,&b,&c);
    add(a,b,c); add(b,a,c);
   }
 }
inline void swap(int f, int t)
 {
  int aux;
  aux=Nod[f]; Nod[f] = Nod[t]; Nod[t]=aux;
  aux=poz[H[f]]; poz[H[f]]=poz[H[t]]; poz[H[t]]=aux;
  aux=H[f]; H[f]=H[t]; H[t]=aux;
  
 }
void downheap(int t) // duc in jos elementul de pe pozitia k
 {
  int f;
  do
   {
     f=0;
     if(2*t <= N) f=2*t;
     if(2*t+1 <= N && c[H[f]] > c[H[2*t+1]]) f=2*t+1;
     if(c[H[f]] > c[H[t]]) f=0;
     if(f)
      {
       swap(t,f);
       t=f;
      }
   }
  while(f);
 }
void upheap(int f)
 {
  int t=f/2;
  while(t && c[H[t]] > c[H[f]])
   {
    swap(t,f);
    t=t/2; f=f/2;
   }
 }
int s;
Graf *Arb[Nmax];
inline void insert(int x, int y, int cst)
 {
  Graf *q;
  q=new Graf;
  q->vf=y; q->cst=cst; q->urm=Arb[x];
  Arb[x]=q;
 }
void vezi()
 {
  Graf *q;
  int i;
  for(i=1;i<=n-1;++i)
   {
    fprintf(g,"\n%d: ",i);
    for(q=Arb[i];q;q=q->urm)
     fprintf(g,"(%d,%d) ",q->vf,q->cst);
   }
 }
void apm()
 {
  int i,p, nod;
  memset(c,Inf,sizeof(c));
  memset(poz,-1,sizeof(poz));
  c[1]=0;
  H[1] = 1;
  poz[1] = 1;
  Nod[1] = -1;
  N=1;
  Graf *q;
  for(i=1;i<=n;++i)
   {
    p = H[1]; // introduc nodul p
    nod = Nod[1];  // am muchia (nod,p)

    if(i>1) insert(p,nod, c[p]); insert(nod,p, c[p]);

    viz[p] = 1;

    // elimin varful p din heap

    H[1] = H[N];
    Nod[1] = Nod[N];
    poz[H[1]] = 1;
    N--;
    downheap(1);

    //fac update pt nodurile care nu sunt in arbore

    for(q=G[p];q;q=q->urm)

      if(!viz[q->vf] && c[q->vf] > q->cst)
        {
          c[q->vf] = q->cst;
          if(poz[q->vf] == -1)
            {
              N++;
              poz[q->vf] = N;
              Nod[N] = p;
              H[N] = q->vf;
              upheap(N);
            }
          else
           {
            Nod[poz[q->vf]] = p;
            upheap(poz[q->vf]);
           }
        }

    }
 }
int euler[Nmax], timp[Nmax], nrp;
int pz[Nmax], tata[Nmax], cost[Nmax], fiu[Nmax];
void dfs(int x, int niv, int t, int cst)
 {
  viz[x]=1;
  tata[x]=t;
  cost[x]=cst;
  euler[++nrp] = x;
  pz[x] = nrp;
  timp[nrp] = niv;
  Graf *q;
  for(q=Arb[x];q;q=q->urm)
   if(!viz[q->vf])
    {
     dfs(q->vf, niv+1, x, q->cst);
     euler[++nrp]=x;
     timp[nrp]=niv;
    }
 }
int rmq[14][Nmax];
int mmax[14][Nmax]; // max[j][i] = muchia de cost maxim intre i si al 2^j lea stramos
int log[Nmax];
int str[14][Nmax];//str[j][i] = al 2^j-lea stramos a lui i
inline int max(int x, int y) {return x>y?x:y;}
void rmq_init(int n)
 {
  int i,j;
  for(i=2;i<=n;++i)
   {
   log[i] = log[i/2] + 1;
   }
  for(i=1;i<=n;++i) { rmq[0][i] = i; mmax[0][i] = cost[i]; str[0][i]=tata[i];}
  for(j=1;(1<<j)<=n;++j)
      for(i=1;i<=n;++i)
       {
	 rmq[j][i] = rmq[j-1][i];
	 if(timp[rmq[j][i]] > timp[rmq[j-1][i+(1<<(j-1))]])
	     rmq[j][i] = rmq[j-1][i+(1<<(j-1))];
	 str[j][i] = str[j-1][str[j-1][i]];
	 mmax[j][i] = mmax[j-1][i];
	 if(mmax[j][i] < mmax[j-1][str[j-1][i]])
		mmax[j][i]=mmax[j-1][str[j-1][i]];
       }

 }
int sol;
inline void muchie(int f, int t) //muchia de drum maxim dintre f si t
 {
  //t e stramos a lui f
  int k=log[timp[f]-timp[t]];
  if(f != t)
   {
    sol = max(sol, mmax[k][f]);
    muchie(str[k][f],t);
   }
 }

inline int query(int x, int y)
 {
 int k=log[y-x+1];
 int sol;
 if(timp[rmq[k][x]] > timp[rmq[k][y-(1<<k)+1]])return rmq[k][y-(1<<k)+1];
 return rmq[k][x];
 }
inline int LCA(int x, int y)
 {
  int p1,p2, aux;
  p1=pz[x];
  p2=pz[y];
  if(p2<p1) { aux=p1; p1=p2; p2=aux; }
  int p=query(p1,p2); //returneaza pozitia elem minim dintre p1 si p2.
  return euler[p];
 }
int drum(int f, int t)
 {
 int m=0;
 while(f!=t)
  {
   if(cost[f] > m ) m=cost[f];
   f=tata[f];
  }

 return m;
 }
int main()
 {
  read();
  apm();       // Creez arborele
  memset(viz,0,sizeof(viz));
  dfs(1,1,-1,0);    // Creez parcurgerea euleriana si adancimea fiecarui nod+tata[]
  rmq_init(nrp); // Calculez matricea rmq[][]
  int x,y,solu,n1,n2;
 // fprintf(g,"%d\n",LCA(1,6));
  while(K--)
   {
    fscanf(f,"%d%d",&x,&y);
    int nod = LCA(x,y);
    sol=0; muchie(x,nod); n1 = sol;
    sol=0; muchie(y,nod); n2 = sol;
    solu=max(n1,n2);
    fprintf(g,"%d\n",solu);
   }
  return 0;
  }