Cod sursa(job #1709626)

Utilizator PlayHPPet Rescue PlayHP Data 28 mai 2016 13:07:55
Problema Revolta Scor 100
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 4.2 kb
#include<cstdio>
#include<vector>
#include<cstring>
#define MAXN 100010
using namespace std;
vector<int> g[MAXN];
int length[MAXN],bestNode;
int v[MAXN],mark[MAXN],best[MAXN],down[MAXN];
int diameterLeft[MAXN],centreLeft[MAXN],distanceLeft[MAXN],bestRight[MAXN],diameterRight[MAXN],centreRight[MAXN],distanceRight[MAXN],bestLeft[MAXN];
void DFS(int node){
    int i;
    if(length[node]>length[bestNode])
        bestNode=node;
    for(i=0;i<g[node].size();i++)
        if(length[g[node][i]]==0){
            length[g[node][i]]=length[node]+1;
            DFS(g[node][i]);
        }
}
int maximum(int a,int b){
    if(a<b)
        return b;
    return a;
}
int minimum(int a,int b){
    if(a>b)
        return b;
    return a;
}
void DFSDown(int node,int father){
    int i;
    best[node]=1;
    for(i=0;i<g[node].size();i++)
        if(mark[g[node][i]]==0&&g[node][i]!=father){
            DFSDown(g[node][i],node);
            best[node]=maximum(best[node],best[g[node][i]]+1);
        }
}
int main(){
    freopen("revolta.in","r",stdin);
    freopen("revolta.out","w",stdout);
    int tests,test,n,i,x,y,first,second,current,node,diameter,currentCentre,answer;
    scanf("%d",&tests);
    for(test=1;test<=tests;test++){
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            g[i].clear();
        for(i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            x++;
            y++;
            g[x].push_back(y);
            g[y].push_back(x);
        }
        memset(length,0,sizeof(length));
        length[1]=1;
        bestNode=0;
        DFS(1);
        first=bestNode;
        memset(length,0,sizeof(length));
        length[bestNode]=1;
        bestNode=0;
        DFS(first);
        second=bestNode;
        node=second;
        current=0;
        memset(mark,0,sizeof(mark));
        while(length[node]!=1){
            current++;
            mark[node]=1;
            v[current]=node;
            for(i=0;i<g[node].size();i++)
                if(length[g[node][i]]==length[node]-1){
                    node=g[node][i];
                    break;
                }
        }
        mark[node]=1;
        current++;
        v[current]=node;
        diameter=current;
        for(i=1;i<=diameter;i++){
            DFSDown(v[i],0);
            down[i]=best[v[i]]-1;
        }
        diameterLeft[1]=0;
        centreLeft[1]=1;
        distanceLeft[1]=0;
        bestRight[1]=0;
        for(i=2;i<=diameter;i++){
            diameterLeft[i]=maximum(diameterLeft[i-1],i-1+down[i]);
            currentCentre=centreLeft[i-1];
            if(i-currentCentre+down[i]<=bestRight[i-1]){
                centreLeft[i]=centreLeft[i-1];
                distanceLeft[i]=distanceLeft[i-1];
                bestRight[i]=bestRight[i-1];
            }
            else{
                while(i-currentCentre+down[i]>currentCentre-1)
                    currentCentre++;
                centreLeft[i]=currentCentre;
                distanceLeft[i]=maximum(currentCentre-1,i-currentCentre+down[i]);
                bestRight[i]=i-currentCentre+down[i];
            }
        }
        diameterRight[diameter]=0;
        centreRight[diameter]=diameter;
        distanceRight[diameter]=0;
        bestLeft[diameter]=0;
        for(i=diameter-1;i>=1;i--){
            diameterRight[i]=maximum(diameterRight[i+1],diameter-i+down[i]);
            currentCentre=centreRight[i+1];
            if(currentCentre-i+down[i]<=bestLeft[i-1]){
                centreRight[i]=centreRight[i-1];
                distanceRight[i]=distanceRight[i-1];
                bestLeft[i]=bestLeft[i-1];
            }
            else{
                while(currentCentre-i+down[i]>diameter-currentCentre)
                    currentCentre--;
                centreRight[i]=currentCentre;
                distanceRight[i]=maximum(diameter-currentCentre,currentCentre-i+down[i]);
                bestRight[i]=currentCentre-i+down[i];
            }
        }
        answer=diameter;
        for(i=1;i<diameter;i++)
            answer=minimum(answer,maximum(maximum(diameterLeft[i],diameterRight[i+1]),distanceLeft[i]+distanceRight[i+1]+1));
        printf("%d\n",answer);
    }

    return 0;
}