Cod sursa(job #982211)

Utilizator danalex97Dan H Alexandru danalex97 Data 8 august 2013 20:07:22
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.71 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

ifstream F("radiatie.in");
ofstream G("radiatie.out");

#define IT(type) vector<type>::iterator

#define cost first
#define x second.first
#define y second.second

#define lca first
#define ord second

const int Nmax = 15010;
const int Mmax = 30010;

typedef pair<int,int> Pair;
typedef pair<int,Pair> edge;

edge E[Mmax];
int N,M,Q,Gr[Nmax],Cost[Nmax];

vector<int> Cst[Nmax];
vector<int> V[Nmax];
vector<Pair> W[Nmax];

int Grup(int i)
{
    if (Gr[i] == i) return i;
    Gr[i] = Grup(Gr[i]);
    return Gr[i];
}

void Union(int i,int j)
{   Gr[ Grup(i) ] = Grup(j) ; }

void Get_APM()
{
    F>>N>>M>>Q;
    for (int i=1;i<=N;++i)
        Gr[i]=i;
    for (int i=1;i<=M;++i)
        F>>E[i].x>>E[i].y>>E[i].cost;

    sort(E+1,E+M+1);
    for (int i=1;i<=M;++i)
        if ( Gr[Grup(E[i].x)] != Gr[Grup(E[i].y)] )
        {
            V[E[i].x].push_back(E[i].y);
            Cst[E[i].x].push_back(E[i].cost);
            V[E[i].y].push_back(E[i].x);
            Cst[E[i].y].push_back(E[i].cost);
            Union( E[i].x , E[i].y );
        }
}

#undef x
#undef y

int L,Euler[Nmax<<2],First[Nmax],Last[Nmax],Lvl[Nmax];
int Dad[Nmax];

void Get_euler(int nod,int dad)
{
    Euler[++L] = nod;
    First[nod] = L;
    Dad[nod] = dad;
    Lvl[nod] = Lvl[dad]+1;
    Last[nod] = L;
    for (IT(int) it=V[nod].begin();it!=V[nod].end();++it)
        if ( *it != dad )
        {
            Get_euler( *it,nod );
            Euler[++L] = nod;
            Last[nod] = L;
        }
}

int A[Nmax<<4];

#define left ( nod*2 )
#define right ( nod*2+1 )

void Get(int nod,int& Min)
{
    if ( Lvl[A[nod]] < Lvl[Min] ) Min = A[nod];
}

void Update(int nod,int st,int dr,int val,int poz)
{
    if ( st == dr )
    {
        A[nod] = val;
        return;
    }

    int mid = ( st + dr ) / 2;
    if ( poz <= mid ) Update(left,st,mid,val,poz);
    if ( poz > mid ) Update(right,mid+1,dr,val,poz);

    Get(left,A[nod]);
    Get(right,A[nod]);
}

int Min;

void Query(int nod,int st,int dr,int start,int stop)
{
    if ( start <= st && dr <= stop )
    {
        Get(nod,Min);
        return;
    }

    int mid = ( st + dr ) / 2;
    if ( start <= mid ) Query(left,st,mid,start,stop);
    if ( stop > mid ) Query(right,mid+1,dr,start,stop);
}

int LCA(int x,int y)
{
    x = First[x];
    y = First[y];
    Min = 0;
    Query(1,1,L,x,y);
    return Min;
}

int Aint[Nmax<<2],Max;

void get(int nod,int& Max)
{
    if ( Cost[Aint[nod]] > Cost[Max] )
        Max = Aint[nod];
}

void update(int nod,int st,int dr,int val,int poz)
{
    if ( st == dr )
    {
        Aint[nod] = val;
        return;
    }

    int mid = ( st + dr ) / 2;
    if ( poz <= mid ) update(left,st,mid,val,poz);
    if ( poz > mid ) update(right,mid+1,dr,val,poz);

    Aint[nod] = 0;
    get(left,Aint[nod]);
    get(right,Aint[nod]);
}

void query(int nod,int st,int dr,int start,int stop)
{
    if ( start <= st && dr <= stop )
    {
        get(nod,Max);
        return;
    }

    int mid = ( st + dr ) / 2;
    if ( start <= mid ) query(left,st,mid,start,stop);
    if ( stop > mid ) query(right,mid+1,dr,start,stop);
}

#define root 1

void Find_cost(int nod,int now)
{
    Cost[nod] = now;
    N = max(N,Lvl[nod]);
    for (unsigned int i=0;i<V[nod].size();++i)
        if ( V[nod][i] != Dad[nod] )
            Find_cost(V[nod][i],Cst[nod][i]);
}

int Sol[Mmax],Pass[Nmax];

void Solve(int nod)
{
    Pass[nod] = 1;
    for (unsigned int i=0;i<W[nod].size();++i)
    {
        int lft = W[nod][i].lca;
        int where = W[nod][i].ord;
        Max = 0 , query(1,1,N,Lvl[lft],Lvl[nod]);
        Sol[where] = max( Cost[Max] , Sol[where] );
    }
    for (unsigned int i=0;i<V[nod].size();++i)
    {
        int now = V[nod][i];
        if ( now != Dad[nod] )
        {
            update(1,1,N,now,Lvl[nod]);
            Solve(now);
            update(1,1,N,0,Lvl[nod]);
        }
    }
}

int main()
{
    Get_APM();

    Lvl[0] = 0;
    for (int i=1;i<=N;++i)
        if ( Lvl[i] == 0 )
            Get_euler(i,0);
    Lvl[0] = 100010;

    for (int i=1;i<=L;++i)
        Update( 1,1,L,Euler[i],i );

    for (int i=1,x,y;i<=Q;++i)
    {
        F>>x>>y;
        int low = LCA(min(x,y),max(x,y));
        W[x].push_back( make_pair( low,i ) );
        W[y].push_back( make_pair( low,i ) );
    }

    Cost[0] = -1;
    for (int i=1;i<=N;++i)
        if ( Cost[i] == 0 )
            Find_cost(i,0);
    for (int i=1;i<=N;++i)
        if ( Pass[i] == 0 )
            Solve(i);

    for (int i=1;i<=Q;++i)
        G<<Sol[i]<<'\n';
}