Cod sursa(job #7985)

Utilizator astronomyAirinei Adrian astronomy Data 23 ianuarie 2007 16:02:39
Problema Radiatie Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 3.27 kb
#include <stdio.h>
#include <stdlib.h>

#define MAX_N (1 << 14)
#define MAX_M (1 << 16)
#define LOGN 14
#define max(a,b) ((a) > (b) ? (a) : (b))

typedef struct edge { int x, y, c; } edge;

int N, M, K, q[MAX_N][2];
int deg[MAX_N], *G[MAX_N], *C[MAX_N];

int dfn[MAX_N], cost[MAX_N], T[MAX_N], viz[MAX_N];

int tata[MAX_N], rank[MAX_N];
int A[LOGN][MAX_N], Max[LOGN][MAX_N];

edge B[MAX_M];

void add_edge(int u, int v, int c)
{
    deg[u]++, deg[v]++;

    G[u] = (int*) realloc(G[u], sizeof(int)*(deg[u]+2));
    G[v] = (int*) realloc(G[v], sizeof(int)*(deg[v]+2));
    C[u] = (int*) realloc(C[u], sizeof(int)*(deg[u]+2));
    C[v] = (int*) realloc(C[v], sizeof(int)*(deg[v]+2));

    G[u][deg[u]] = v, G[v][deg[v]] = u;
    C[u][deg[u]] = c, C[v][deg[v]] = c;
}

int find(int x)
{
    while(tata[x])
        x = tata[x];
    return x;
}

void uneste(int rx, int ry)
{
    if(rank[rx] > rank[ry])
        tata[ry] = rx;
    else
        tata[rx] = ry, rank[ry] += (rank[rx] == rank[ry]);
}

void dfs(int x, int d)
{
    int i, v;
    for(i = 1; i <= deg[x]; i++)
    {
        v = G[x][i];
        if(!viz[v])
            dfn[v] = d, viz[v] = 1, T[v] = x,
            cost[v] = C[x][i], dfs(v, d+1);
    }
}

void preproc(void)
{
    int i, j;

    for(i = 1; i <= N; i++)
        A[0][i] = T[i], Max[0][i] = cost[i];

    for(i = 1; i < LOGN; i++)
     for(j = 1; j <= N; j++)
        A[i][j] = A[i-1][A[i-1][j]],
        Max[i][j] = max(Max[i-1][j], Max[i-1][A[i-1][j]]);
}

int get_tata(int x, int t)
{
    int r, nod;
    for(r = 0, nod = x; t > 0; t >>= 1, r++)
     if(t & 1)
        nod = A[r][nod];
    return nod;
}

int get_max(int x, int t)
{
    int r, nod, m = 0;
    for(r = 0, nod = x; t > 0; t >>= 1, r++)
     if(t & 1)
        m = max(m, Max[r][nod]), nod = A[r][nod];
    return m;
}

int query(int x, int y)
{
    int st, dr, m, r, t1, t2;

    // lca

    st = 0, dr = dfn[x];
    while(st <= dr)
    {
        m = (st+dr) >> 1;
        t1 = get_tata(x, dfn[x]-m), t2 = get_tata(y, dfn[y]-m);
        if(t1 == t2)
            r = m, st = m+1;
        else
            dr = m-1;
    }

    t1 = get_max(x, dfn[x]-r), t2 = get_max(y, dfn[y]-r);

    return max(t1, t2);
}

int cmp(const void *a, const void *b)
{
    return ((edge*)a)->c - ((edge*)b)->c;
}

void solve_and_write(void)
{
    int i, x, y, rx, ry, c;

    qsort(B, M, sizeof(B[0]), cmp);
    
    for(i = 0; i < M; i++)
    {
        x = B[i].x, y = B[i].y, c = B[i].c;
        rx = find(x), ry = find(y);
        if(rx == ry)
            continue ;
        uneste(rx, ry);
        add_edge(x, y, c);
    }

    for(i = 1; i <= N; i++)
     if(!viz[i])
        viz[i] = 1, dfs(i, 1);

    preproc();
    
    for(i = 1; i <= K; i++)
        printf("%d\n", query(q[i][0], q[i][1]));
}

void read_data(void)
{
    int i;

    scanf("%d %d %d\n", &N, &M, &K);

    for(i = 0; i < M; i++)
        scanf("%d %d %d\n", &B[i].x, &B[i].y, &B[i].c);

    for(i = 1; i <= K; i++)
        scanf("%d %d\n", &q[i][0], &q[i][1]);
}

int main(void)
{
    freopen("radiatie.in", "rt", stdin);
    freopen("radiatie.out", "wt", stdout);

    read_data();
    solve_and_write();

    return 0;
}