Cod sursa(job #595669)

Utilizator Smaug-Andrei C. Smaug- Data 13 iunie 2011 15:21:00
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.2 kb
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <utility>
using namespace std;

#define MAXN 15010
#define MAXLGN 16
#define MAXM 30010

int C[MAXM];

inline int find(int *T, int x){

  while(x!=T[x])
    x=T[x];

  return x;
}

inline void unite(int *T, int x, int y){
  T[x]=y;
}

int cmp(int a, int b){
  return C[a]<C[b];
}

int main(){

  freopen("radiatie.in", "r", stdin);
  freopen("radiatie.out", "w", stdout);

  int N, M, K, i, j, k, a, b, e, qp, lca, x, y, maxd, dist, up;
  static int X[MAXM], Y[MAXM], IND[MAXM], T[MAXN];
  static int Q[MAXN], use[MAXN], E[MAXN<<2], L[MAXN<<2], F[MAXN];
  static int RMQ[MAXLGN][MAXN<<2], lg[MAXN<<2], S[MAXLGN][MAXN<<2], D[MAXLGN][MAXN<<2];
  pair<int,int> P[MAXN];
  vector< pair<int,int> > G[MAXN];
  vector< pair<int,int> >::iterator dfs[MAXN];

  scanf("%d%d%d", &N, &M, &K);
  for(i=1; i<=M; i++)
    scanf("%d%d%d", X+i, Y+i, C+i);

  // Minimum spanning tree

  for(i=1; i<=N; i++)
    T[i]=i;
  for(i=1; i<=M; i++)
    IND[i]=i;
  

  sort(IND+1, IND+M+1, cmp);

  for(i=1; i<=M; i++)
    if((a=find(T, X[IND[i]])) != (b=find(T, Y[IND[i]]))){
      unite(T, a, b);
      G[X[IND[i]]].push_back(make_pair(Y[IND[i]], C[IND[i]]));
      G[Y[IND[i]]].push_back(make_pair(X[IND[i]], C[IND[i]]));
    }
      
  memset(use, 0, sizeof(use));
  memset(F, 0, sizeof(F));

  // Euler + level (DFS)

  Q[0]=1; qp=0; dfs[0]=G[1].begin();
  use[1]=1; e=0;

  while(qp>=0){
    if(!qp || qp!=L[e]){
      E[++e]=Q[qp]; L[e]=qp;
      if(!F[Q[qp]])
	F[Q[qp]]=e;
    }
    
    if(dfs[qp] != G[Q[qp]].end()){
      if(!use[dfs[qp]->first]){
	Q[qp+1]=dfs[qp]->first;
	dfs[qp+1]=G[Q[qp+1]].begin();
	use[Q[qp+1]]=1;
	P[Q[qp+1]].first=Q[qp];
	P[Q[qp+1]].second=dfs[qp]->second;
	qp++;
      }
      else
	dfs[qp]++;
    }
    else {
      qp--;
      dfs[qp]++;
    }

  }

  // RMQ

  for(i=1; i<=e; i++)
    RMQ[0][i]=i;
  for(i=1; (1<<i)<=e; i++)
    for(j=1; j+(1<<i)-1 <= e; j++){
      if(L[RMQ[i-1][j]] < L[RMQ[i-1][j+(1<<(i-1))]])
	RMQ[i][j]=RMQ[i-1][j];
      else
	RMQ[i][j]=RMQ[i-1][j+(1<<(i-1))];
    }

  for(i=1; i<=N; i++){
    S[0][i]=P[i].first;
    D[0][i]=P[i].second;
  }
  for(i=1; (1<<i)<=N; i++)
    for(j=1; j+(1<<i)-1 <= e; j++){
      S[i][j]=S[i-1][S[i-1][j]];
      D[i][j]=max(D[i-1][j], D[i-1][S[i-1][j]]);
    }

  lg[1]=0;
  for(i=2; i<=e; i++)
    lg[i]=lg[i>>1]+1; 

  // Query

  for(i=1; i<=K; i++){
    scanf("%d%d", &a, &b);
    
    // LCA

    x=F[a], y=F[b];
    if(x>y)
      swap(x,y);
    k=lg[y-x+1];
    if(L[RMQ[k][x]] < L[RMQ[k][y-(1<<k)+1]])
      lca=RMQ[k][x];
    else
      lca=RMQ[k][y-(1<<k)+1];
    lca=E[lca];
    
    // MAX DIST

    maxd=0;

    if(a!=lca){
      dist=L[F[a]]-L[F[lca]];
      k=lg[dist];
      maxd=max(maxd, D[k][a]);

      // move upwards to secure 2nd interval
      up=dist-(1<<k);
      x=a;
      while(up){
	x=S[lg[up]][x];
	up-=1<<lg[up];
      }

      maxd=max(maxd, D[k][x]);
    }

    if(b!=lca){
      dist=L[F[b]]-L[F[lca]];
      k=lg[dist];
      maxd=max(maxd, D[k][b]);

      // move upwards to secure 2nd interval
      up=dist-(1<<k);
      x=b;
      while(up){
	x=S[lg[up]][x];
	up-=1<<lg[up];
      }

      maxd=max(maxd, D[k][x]);
    }

    printf("%d\n", maxd);

  }  

  return 0;

}