Cod sursa(job #1710014)

Utilizator Spiromanii_MessiUNIBUCThrowTerror Spiromanii_Messi Data 28 mai 2016 14:46:26
Problema Revolta Scor 0
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 3.9 kb
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

const int N = 100003;

vector <int> graph [N];
int n;
int d [N], last [N], ra, rb, l [N];
bool used [N];

void read () {
    int i, a, b;

    scanf ("%d", &n);

    for (i = 1; i < n; i ++) {
        scanf ("%d%d", &a, &b);
        a ++ ; b ++;
        graph [a].push_back (b);
        graph [b].push_back (a);
    }
}

inline bool e_ok (int a, int b) {
    if (a == ra && b == rb)
        return 0;
    if (a == rb && b == ra)
        return 0;
    return 1;
}

void dfs (int x) {
    vector <int> :: iterator it;

    used [x] = 1;
    for (it = graph [x].begin (); it != graph [x].end (); ++ it)
        if (!used [*it] && e_ok (x, *it) == 1) {
            d [*it] = d [x] + 1;
            last [*it] = x;
            dfs (*it);
        }
}

int makeDiametru () {
    int i, maxim, s, f;

    maxim = -1;
    memset (used, 0, sizeof (used));
    memset (d, 0, sizeof (d));
    dfs (1);
    for (i = 1; i <= n; i ++)
        if (d [i] > maxim) {
            maxim = d [i];
            s = i;
        }
    memset (used, 0, sizeof (used));
    memset (d, 0, sizeof (d));
    dfs (s);
    maxim = -1;
    for (i = 1; i <= n; i ++)
        if (d [i] > maxim) {
            maxim = d [i];
            f = i;
        }
    return maxim + 1;
}

int placeEdge (const int &poz) {
    int i, c1, c2, c3, c4, h, ans = (1ll << 31) - 1;

    ra = l [poz];
    rb = l [poz + 1];

    //1 la poz
    c1 = poz / 2;
    c2 = c1 + 1;
    // poz + 1 .. l [0]
    h = l [0] - (poz + 1) + 1;
    c3 = poz + h / 2;
    c4 = poz + h / 2 + 1;

    if (c1)
        c1 = l [c1];
    c2 = l [c2];
    c3 = l [c3];
    c4 = l [c4];

    // c1 c3
    if (e_ok (c1, c3) == 1 && c1) {
        graph [c1].push_back (c3);
        graph [c3].push_back (c1);

        ans = min (ans, makeDiametru ());

        graph [c1].pop_back ();
        graph [c3].pop_back ();
    }
    // c1 c4
    if (e_ok (c1, c4) == 1 && c1) {
        graph [c1].push_back (c4);
        graph [c4].push_back (c1);

         ans = min (ans, makeDiametru ());

        graph [c1].pop_back ();
        graph [c4].pop_back ();
    }
    // c2 c3
    if (e_ok (c2, c3) == 1) {
        graph [c2].push_back (c3);
        graph [c3].push_back (c2);

         ans = min (ans, makeDiametru ());

        graph [c2].pop_back ();
        graph [c3].pop_back ();
    }
    // c2 c4
    if (e_ok (c2, c4) == 1) {
        graph [c2].push_back (c4);
        graph [c4].push_back (c2);

        ans = min (ans, makeDiametru ());

        graph [c2].pop_back ();
        graph [c4].pop_back ();
    }

    return ans;
}

void solve () {
    int i, maxim, s, ans, f, diametru;

    maxim = -1;
    ra = rb = 0;
    memset (used, 0, sizeof (used));
    dfs (1);
    for (i = 1; i <= n; i ++)
        if (d [i] > maxim) {
            maxim = d [i];
            s = i;
        }
    memset (used, 0, sizeof (used));
    memset (d, 0, sizeof (d));
    dfs (s);
    maxim = -1;
    for (i = 1; i <= n; i ++)
        if (d [i] > maxim) {
            maxim = d [i];
            f = i;
        }
    diametru = maxim + 1;
    ans = diametru;

    l [0] = 0;
    for (i = f; i != s; i = last [i])
        l [++ l [0]] = i;
    l [++ l [0]] = s;

    ans = min (ans, placeEdge (diametru / 2));

        ans = min (ans, placeEdge (diametru / 2 + 1));

    printf ("%d\n", ans - 1);
}

void init () {
    memset (last, 0, sizeof (last));
    memset (d, 0, sizeof (d));
    for (int i = 1; i <= n; i ++)
        if (!graph [i].empty ())
            graph [i].clear ();
}

int main () {
    int T, t;

    freopen ("revolta.in", "r", stdin);
    freopen ("revolta.out", "w", stdout);

    scanf ("%d", &T);
    for (t = 1; t <= T; t ++) {
        read ();
        solve ();
        init ();
    }
    return 0;
}