Cod sursa(job #2014570)

Utilizator ionanghelinaIonut Anghelina ionanghelina Data 23 august 2017 22:13:28
Problema Radiatie Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.64 kb
#include<bits/stdc++.h>
#define maxN 150005
#define maxM 600005
#define inf 2000000000
using namespace std;

typedef struct tip
{
    int x,y,c;
};
vector<pair<int,int> > v[maxN];
bool cmp(tip a,tip b)
{
    return a.c<b.c;
}
int t[maxN],A[4*maxN+5],dp[maxN],h[8*maxN+5],dh,Lev[2*maxN+5],ap[maxN],best,fat[maxN],fEdge[maxN];
int anc[150][maxN],maxim[150][maxN];
int loga[maxN];
bool seen[maxN];
inline int GetRoot(int x)
{
    int root=x;
    int y=x;
    while(t[x]>0)
    {
        x=t[x];
        root=x;
    }
    while(t[y]>0)
    {
        t[y]=root;
        y=t[y];
    }
    return root;
}


inline void Unite(int x,int y)
{
    if(t[x]<t[y])
    {
        t[x]+=t[y];
        t[y]=x;
    }
        else
    {
        t[y]+=t[x];
        t[x]=y;
    }
}

tip Edges[maxM];
vector<tip> APMEdges;
int n,m,q,level[maxN];
inline void BuildAPM()
{
    sort(Edges+1,Edges+m+1,cmp);
    int selected=0;
    for(int i=1;i<=n;i++)
        t[i]=-1;
    for(int i=1;i<=m && selected<(n-1);i++)
    {
        int x,y,c;
        x=Edges[i].x;
        y=Edges[i].y;
        c=Edges[i].c;
        int rootx=GetRoot(x);
        int rooty=GetRoot(y);
        if(rootx!=rooty)
        {
            selected++;
            APMEdges.push_back(Edges[i]);
            Unite(rootx,rooty);
        }
    }

    for(vector<tip>::iterator it=APMEdges.begin();it!=APMEdges.end();it++)
    {
        v[it->x].push_back({it->y,it->c});
        v[it->y].push_back({it->x,it->c});
    }
}
inline void Euler(int nod,int niv)
{
    h[++dh]=nod;
    Lev[dh]=niv;
    ap[nod]=dh;
    level[nod]=niv;
    seen[nod]=1;
    for(vector<pair<int,int> >::iterator it=v[nod].begin();it!=v[nod].end();it++)
    {
        if(!seen[it->first]) Euler(it->first,niv+1);
        h[++dh]=nod;
        Lev[dh]=niv;
    }
}

inline void dfs(int nod)
{
    seen[nod]=1;
    for(vector<pair<int,int> >::iterator it=v[nod].begin();it!=v[nod].end();it++)
    {
        if(!seen[it->first])
        {
            fat[it->first]=nod;
            fEdge[it->first]=it->second;
            dfs(it->first);
        }
    }
}

inline void Build(int nod,int st,int dr)
{
    if(st==dr)
    {
        A[nod]=st;
    }
        else

    {
        int mid=(st+dr)>>1;
        Build(2*nod,st,mid);
        Build(2*nod+1,mid+1,dr);
        if(Lev[A[2*nod]]<Lev[A[2*nod+1]]) A[nod]=A[2*nod];
            else A[nod]=A[2*nod+1];
    }
}
int sol=inf;
inline void Query(int nod,int st,int dr,int a,int b)
{
    if(a<=st && dr<=b)
    {
        if(Lev[A[nod]]<sol)
        {
            sol=Lev[A[nod]];
            best=A[nod];
        }
    }
        else
    {
        int mid=(st+dr)>>1;
        if(a<=mid) Query(2*nod,st,mid,a,b);
        if(b>mid) Query(2*nod+1,mid+1,dr,a,b);
    }
}

inline void BuildLCA()
{
    Euler(1,1);
    Build(1,1,dh);
    memset(seen,0,sizeof(seen));
    dfs(1);
}


inline void BuildAncestors()
{
    loga[1]=0;
    for(int i=2;i<=n;i++)
        loga[i]=1+loga[i>>1];
    for(int i=1;i<=n;i++)
    {
        anc[0][i]=fat[i];
        maxim[0][i]=fEdge[i];
    }
    for(int nivel=1;nivel<=loga[n];nivel++)
    {
        for(int i=1;i<=n;i++)
        {
            anc[nivel][i]=anc[nivel-1][anc[nivel-1][i]];
            maxim[nivel][i]=max(maxim[nivel-1][i],maxim[nivel-1][anc[nivel-1][i]]);
        }
    }
}
inline int Solve(int x,int y)
{
    int xa=ap[x];
    int ya=ap[y];
    if(xa>ya) swap(xa,ya);
    sol=inf;
    Query(1,1,dh,xa,ya);
   // return dp[x]-dp[best]+dp[y]-dp[best];
    int nivel,ans1,ans2;
    best=h[best];
    nivel=level[x]-level[best];
    ans1=0;
    ans2=0;
    while(nivel)
    {
        ans1=max(ans1,maxim[loga[nivel]][x]);
        x=anc[loga[nivel]][x];
        nivel-=(1<<loga[nivel]);
    }
    nivel=level[y]-level[best];
    while(nivel)
    {
        ans2=max(ans2,maxim[loga[nivel]][y]);
        y=anc[loga[nivel]][y];
        nivel-=(1<<loga[nivel]);
    }
    return max(ans1,ans2);
}

int x,y,c,f[maxN];
int main()
{
    freopen("radiatie.in","r",stdin);
    freopen("radiatie.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&c);
        Edges[i]={x,y,c};
        f[x]++;
        f[y]++;
    }
    int j;
    for(int i=1;i<=n;i++)
    {
        if(f[i]) {j=i;break;}
    }
    for(int i=1;i<=n;i++)
    {
        if(!f[i])
        {
            Edges[++m]={j,i,inf};
        }
    }
    BuildAPM();
    BuildLCA();
    BuildAncestors();
    while(q--)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",Solve(x,y));
    }
    return 0;
}