Cod sursa(job #1709960)

Utilizator UBB_HakunaMatataUBB Cozma Nechita Pop UBB_HakunaMatata Data 28 mai 2016 14:35:36
Problema Revolta Scor 0
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 4.69 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("revolta.in");
ofstream fout("revolta.out");
#define MAX 100010
typedef vector <int> :: iterator iter;
vector <int> G[MAX];
#define cout fout

int rmq[20][2 * MAX];
int lvl[MAX], f[MAX];
int dr;
int doi[2 * MAX];
void df(int nod, int dad)
{
    // cout << nod << " ";
    lvl[nod] = lvl[dad] + 1;
    rmq[0][++dr] = nod;
    f[nod] = dr;
    for(iter it = G[nod].begin() ; it != G[nod].end() ; it++)
    {
        if(*it == dad)
            continue;
        df(*it, nod);
        rmq[0][++dr] = nod;
    }
}

int n;

void build_rmq()
{
    int k, i;
    for(k = 1 ; (1<<k) <= dr ; k++)
    {
        for(i = 1 ; i + (1<<k) - 1 <= dr ; i++)
        {
            if(lvl[rmq[k - 1][i]] < lvl[rmq[k - 1][i + (1<<(k - 1))]])
                rmq[k][i] = rmq[k - 1][i];
            else
                rmq[k][i] = rmq[k - 1][i + (1<<(k - 1))];
        }
    }
    doi[1] = 0;
    for(i = 2 ; i <= dr ; i++)
        doi[i] = doi[i / 2] + 1;
}

int lca(int x, int y)
{
    x = f[x];
    y = f[y];
    if(x > y)
        swap(x, y);
    int lg = doi[(y - x + 1)];
    if(lvl[rmq[lg][x]] < lvl[rmq[lg][y - (1<<lg) + 1]])
        return rmq[lg][x];
    return rmq[lg][y - (1<<lg) + 1];
}

void init()
{
    for(int i = 1 ; i <= n ; i++)
        G[i].clear();
    dr = 0;
}

int dist(int x, int y)
{
    return lvl[x] + lvl[y] - 2 * lvl[lca(x, y)] + 1;
}

int tata[MAX];
int lvl2[MAX], nnext[MAX];
void diam(int nod, int dad)
{
    lvl2[nod] =lvl2[dad] + 1;
    tata[nod] = dad;
    for(auto it : G[nod])
    {
        if(it == dad)
            continue;
        diam(it, nod);
    }

}

pair<int, int> find_diametru(pair<int, int> a, pair<int, int> b)
{
    int mxdist = max(max(dist(a.first, a.second), dist(a.first, b.first)),
                     max(max(dist(a.first, b.second), dist(a.second, b.first)),
                     max(dist(a.second, b.second), dist(b.first, b.second))));
    if(dist(a.first, a.second) == mxdist)
        return a;
    if(dist(a.first, b.first) == mxdist)
        return make_pair(a.first, b.first);
    if(dist(a.first, b.second) == mxdist)
        return make_pair(a.first, b.second);
    if(dist(a.second, b.first) == mxdist)
        return make_pair(a.second, b.first);
    if(dist(a.second, b.second) == mxdist)
        return make_pair(a.second, b.second);
    return b;


}

pair<int, int> diametru[MAX];
bool special[MAX];

void build(int nod, int dad)
{
    diametru[nod] = make_pair(nod, nod);
    for(auto it : G[nod])
    {
        if(it == dad || special[it])
            continue;
        build(it, nod);
        diametru[nod] = find_diametru(diametru[nod], diametru[it]);

    }
}

pair<int, int> dp1[MAX], dp2[MAX];

int main()
{
    int t, i, x, y, nod, nod2;
    fin >> t;
    while(t--)
    {

        fin >> n;
        init();

        for(i = 1 ; i < n ; i++)
        {

            fin >> x >> y;
            x++;
             y++;

            /// [RPSTI;L SCOATE AS;DLFKJAS;LKDHFALKJHFBGKJADFK;G'JL

            G[x].push_back(y);
            G[y].push_back(x);
        }

        df(1, 0); ///vezi boule baga din 1

        build_rmq();

        nod = 1;
        for(i = 1 ; i <= n ; i++)
            if(lvl[i] > lvl[nod])
                nod = i;
        diam(nod, 0);
        nod2 = 1;
        for(i = 1 ; i <= n ; i++)
            if(lvl2[i] > lvl2[nod2])
                nod2 = i;
      //  cout << nod << "! " << nod2 << "\n";
        for(i = nod2 ; i != 0 ; i = tata[i])
        {
            special[i] = 1;
            nnext[tata[i]] = i;
        }
        for(i = nod2 ; i != 0 ; i = tata[i])
        {
            build(i, 0);
          //  cout << i << " " << diametru[i].first << " " << diametru[i].second << "\n";
        }

        dp1[nod2] = diametru[nod2];

        for(i = tata[nod2] ; i != 0 ; i = tata[i])
        {
            dp1[i] = find_diametru(dp1[nnext[i]], diametru[i]);

        }

        dp2[nod] = diametru[nod];
        nnext[nod2]=0;

        for(i = nnext[nod] ; i != 0 ; i = nnext[i])
        {
            dp2[i] = find_diametru(diametru[i],dp2[tata[i]]);

        }
        int d1, d2;
        int ans = n + 4;
        for(i = nod; i != nod2 ; i = nnext[i])
        {

            d1 = dist(dp2[i].first, dp2[i].second);
            d2 = dist(dp1[nnext[i]].first, dp1[nnext[i]].second);


            ans = min(d1/ 2 +1 + d2 / 2+1, ans);
            pair<int, int> aux = find_diametru(dp2[i], dp1[nnext[i]]);
            ans = min(ans, dist(aux.first, aux.second));
        }
        cout << ans - 1 << "\n";
    }
}