Cod sursa(job #1016317)

Utilizator narcis_vsGemene Narcis - Gabriel narcis_vs Data 26 octombrie 2013 01:03:49
Problema Radiatie Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.66 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define IT vector< int > ::iterator
#define NODE (node+decalaj)
#define LeftSon (2*node)
#define RightSon (2*node+1)
#define In "radiatie.in"
#define Out "radiatie.out"
#define edge pair < int ,pair < int ,int > >
#define Nmax 15004
#define Mmax 30004
#define X second.first
#define Y second.second
#define cost first
using namespace std;
edge e[Mmax];

ifstream f(In);
ofstream g(Out);

vector< int > Tree[Nmax];
vector<int > el[Nmax];
int niv[Nmax], Root,m ;
int n, ans, L, v[Nmax], LantDim[Nmax];
int nr[Nmax],Lant[Nmax];
int LantFather[Nmax],LantSum[Nmax];
int pos[Nmax], nivFather[Nmax];
int Father[Nmax];
struct DisjointSets
{
    inline void Buid()
    {
        for(int i = 1;i <= n; ++i)
            Father[i] = i;
    }
    inline int Find(int node)
    {
        while(node!=Father[node])
            node = Father[node];
        return node;
    }
    inline void Union(const int x,const int y)
    {
        Father[x] = y;
    }
};
DisjointSets S;
inline void APM()
{
    sort(e+1,e+m+1);
    int i ,x ,y;
    S.Buid();
    for(i = 1;i <= m; ++i)
    {
        x = S.Find(e[i].X) ;
        y = S.Find(e[i].Y) ;
        if(y != x)
        {
           S.Union(x,y);
           Tree[y].push_back(x);
           v[x] = e[i].cost;
        }
    }
}
class SegmentTree
{
    public :
    inline void Build(const int node,const int left,const int right,const int decalaj,int lant)
    {
        if(left == right )
        {
            aint[NODE] = v[el[lant][left]];
            return ;
        }
        int middle = (left + right)>>1;
        Build(LeftSon,left,middle,decalaj,lant);
        Build(RightSon,middle+1,right,decalaj,lant);
        aint[NODE] = max(aint[LeftSon+decalaj],aint[RightSon+decalaj]);
    }
    inline void Query(const int node,const int left,const int right,const int x ,const int y,const int decalaj)
    {
        if(x <= left && right <= y )
        {
            ans = max(ans,aint[NODE]);
            return ;
        }
        int middle = (left + right)>>1;
        if(x<=middle)
            Query(LeftSon,left,middle,x,y,decalaj);
        if(middle+1<=y)
            Query(RightSon,middle+1,right,x,y,decalaj);
    }
    private :int aint[4*Nmax];
};
inline void Erase(const int node,const int Father)
{
    IT  it, del = Tree[node].end();
    for(it = Tree[node].begin();it!=Tree[node].end(); ++it)
        if(*it==Father)
            del = it;
        else
            Erase(*it,node);
    if(del!=Tree[node].end())
        Tree[node].erase(del);
}

inline void DFS(const int node)
{
    IT it;
    bool frunza = 1;
    int SonMAX = 0, lant;
    nr[node] = 1;
    for(it = Tree[node].begin(); it!= Tree[node].end(); ++it)
    {
        niv[*it] = niv[node]+1;
        frunza = 0;
        DFS(*it);
        nr[node] += nr[*it];
        if(nr[*it] > nr[SonMAX])
            SonMAX= *it;
    }
    if(frunza)
    {
        ++L;
        Lant[node] = L;
        LantDim[L] = 1;
        el[L].push_back(node);
        return ;
    }
    lant = Lant[SonMAX];
    Lant[node] = lant;
    ++LantDim[lant];
    el[lant].push_back(node);
    for(it = Tree[node].begin(); it!= Tree[node].end(); ++it)
        if(*it!=SonMAX)
        {
            LantFather[Lant[*it]] = node;
            nivFather[Lant[*it]] = niv[node];
        }
}

inline void Reverse(const int i)
{
    int j,n = LantDim[i],m;
    m =  (n>>1)+ (n&1);
    if(n==1)
        pos[el[i][1]] = 1;
    for(j = 1;j <= m; ++j)
    {
        swap(el[i][j],el[i][n-j+1]);
        pos[el[i][j]] = j;
        pos[el[i][n-j+1]] = n-j+1;
    }
}
SegmentTree A;
int main()
{
    int i,x, k, y;
    f>>n >> m >> k;
    for(i = 1;i <= n; ++i)
    {
        f>> e[i].X >> e[i].Y >>e[i].cost;
        el[i].push_back(0);
    }
    APM();
    for(i=1;i<=n;++i)
        if(Father[i]==i)
        {
            Root = i;
            break ;
        }
    Erase(Root,0);
    niv[Root] = 1;
    DFS(Root);
    for(i = 1;i <= L; ++i)
    {
        Reverse(i);
        if(i>1)
            LantSum[i] = LantSum[i-1] + 4*LantDim[i-1];
        A.Build(1,1,LantDim[i],LantSum[i],i);
    }
    for( ; k; --k)
    {
        f>> x >> y;
        ans = 0;
        while(true)
        {
            if(Lant[x]==Lant[y])
            {
                if(niv[x]>niv[y])
                    swap(x,y);
                if(pos[x]==pos[y])
                    break;
                A.Query(1,1,LantDim[Lant[x]],pos[y],pos[y],LantSum[Lant[x]]);
                break;
            }
            if(nivFather[Lant[x]] < nivFather[Lant[y]])
                swap(x,y);
            A.Query(1,1,LantDim[Lant[x]],1,pos[x],LantSum[Lant[x]]);
            x = LantFather[Lant[x]];
        }
        g<<ans<<"\n";
    }
    f.close();
    g.close();
    return 0;
}