Cod sursa(job #921454)

Utilizator tzipleatudTudor Tiplea tzipleatud Data 20 martie 2013 23:41:30
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.4 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <cstring>
#define NM 15010
#define LM 15
#define cost first
#define node second
#define node1 second.first
#define node2 second.second

using namespace std;

ifstream f("radiatie.in");
ofstream g("radiatie.out");

typedef pair< int, pair<int, int> > PIC;
typedef pair<int, int> PI;

vector<PIC> Edges;
vector<PI> G[NM];
int N, M, K;
bool Vis[NM];
int T[NM], GR[NM];
int Father[NM], Level[NM];
int Ancestors[LM][NM];
int Max[LM][NM];
int CostM[NM];

void Read ()
{
    f >> N >> M >> K;
    for (int i=1; i<=M; i++)
    {
        int a, b, c;
        f >> a >> b >> c;
        Edges.push_back(make_pair(c, make_pair(a, b)));
    }
}

int Root (int x)
{
    int p, y;

    for (p=x; p!=T[p]; p=T[p]);

    for (; x!=T[x]; )
    {
        y=T[x];
        T[x]=p;
        x=T[x];
    }

    return p;
}

void Unite (int x, int y)
{
    if (GR[x]>=GR[y])
    {
        GR[x]+=GR[y];
        T[y]=x;
    }
    else
    {
        GR[y]+=GR[x];
        T[x]=y;
    }
}

void DoAPM ()
{
    int i, a, b, c;

    for (i=1; i<=N; i++)
    {
        T[i]=i;
        GR[i]=1;
    }

    sort(Edges.begin(), Edges.end());

    for (i=0; i<Edges.size(); i++)
    {
        a=Edges[i].node1;
        b=Edges[i].node2;
        c=Edges[i].cost;

        if (Root(a)==Root(b)) continue;

        Unite(T[a], T[b]);
        G[a].push_back(make_pair(c, b));
        G[b].push_back(make_pair(c, a));
    }
}

void BuildTree (int Node, int Lev)
{
    Level[Node]=Lev;
    Vis[Node]=1;

    for (vector<PI>::iterator it=G[Node].begin(); it!=G[Node].end(); ++it)
        if (!Vis[it->node])
        {
            Father[it->node]=Node;
            CostM[it->node]=it->cost;
            BuildTree(it->node, Lev+1);
        }
}

void BuildAncestors ()
{
    int i, j;

    for (i=1; i<=N; i++)
    {
        Ancestors[0][i]=Father[i];
        Max[0][i]=CostM[i];
    }

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

int LCA (int a, int b)
{
    int k, log1, log2;
    if (Level[a]>Level[b])
        swap(a, b);

    for (log1=0; (1 << log1)<Level[a]; ++log1);
    for (log2=0; (1 << log2)<Level[b]; ++log2);

    for (k=log2; k>=0; k--)
        if (Level[b]-(1 << k)>=Level[a])
            b=Ancestors[k][b];

    if (a==b) return a;

    for (k=log1; k>=0; k--)
        if (Ancestors[k][a]!=0 && Ancestors[k][a]!=Ancestors[k][b])
        {
            a=Ancestors[k][a];
            b=Ancestors[k][b];
        }

    return Ancestors[0][a];
}

int UpTo (int x, int z)
{
    if (Level[x]<=Level[z]) return 0;

    int val=0, k, log;

    for (log=0; (1 << log)<Level[x]; ++log);

    for (k=log; k>=0; k--)
        if (Level[x]-(1 << k)>=Level[z])
        {
            val=max(val, Max[k][x]);
            x=Ancestors[k][x];
        }

    return val;
}

void Solve ()
{
    int i, x, y, z;

    for (i=1; i<=K; i++)
    {
        f >> x >> y;

        z=LCA(x, y);

        g << max(UpTo(x, z), UpTo(y, z)) << '\n';
    }
}

int main ()
{
    Read();
    DoAPM();
    BuildTree(1, 1);
    BuildAncestors();
    Solve();

    f.close();
    g.close();

    return 0;
}