Cod sursa(job #1709082)

Utilizator linia_intaiConstantinescu Iordache Ciobanu Noi cei din linia intai linia_intai Data 28 mai 2016 10:50:04
Problema Revolta Scor 0
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 3.96 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
const int MAX_N = 200005;
 
 
vector< pair<int, int> > tree[MAX_N];
int dist[MAX_N];
int father[MAX_N];
int best_length[MAX_N];
int best_diameter[MAX_N];
bool in_chain[MAX_N];
 
int best_left[MAX_N];
int best_right[MAX_N];
 
void dfs_dist(int node, int daddy = 0) {
    for (vector< pair<int, int> > :: iterator it = tree[node].begin(); it != tree[node].end(); ++ it) {
        if (it->first != daddy) {
            dist[it->first] = dist[node] + 1;
            father[it->first] = node;
            dfs_dist(it->first, node);
        }
    }
}
void dfs_chain(int node, int daddy = 0) {
    int a = 0, b = 0;
    for (vector< pair<int, int> > :: iterator it = tree[node].begin(); it != tree[node].end(); ++ it) {
        if (it->first != daddy && !in_chain[it->first]) {
            father[it->first] = node;
            dfs_chain(it->first, node);
            best_diameter[node] = max(best_diameter[node], best_diameter[it->first]);
            if (best_length[it->first] + 1 > a) {
                b = a;
                a = best_length[it->first] + 1;
            } else if (best_length[it->first] + 1 > b) {
                b = best_length[it->first] + 1;
            }
        }
    }
    best_length[node] = a;
    best_diameter[node] = max(best_diameter[node], a + b);
}
 
int main() {
    ifstream cin("revolta.in");
    ofstream cout("revolta.out");
    int tests, n, x, y;
    for (cin >> tests; tests; -- tests) {
        cin >> n;
        for (int i = 1; i <= n; i += 1) {
            tree[i].clear();
        }
        for (int i = 1; i < n; ++ i) {
            cin >> x >> y;
            x += 1;
            y += 1;
            tree[x].push_back(make_pair(y, i));
            tree[y].push_back(make_pair(x, i));
        }
        dist[1] = 0;
        dfs_dist(1);
        int root = 1;
        for (int i = 2; i <= n; ++ i) {
            if (dist[i] > dist[root]) {
                root = i;
            }
        }
        dist[root] = 0;
        dfs_dist(root);
        int leaf = 1;
        for (int i = 2; i <= n; ++ i) {
            if (dist[i] > dist[leaf]) {
                leaf = i;
            }
        }
        vector<int> chain, edges(1, -1);
        while (leaf != root) {
            chain.push_back(leaf);
            in_chain[leaf] = true;
            leaf = father[leaf];
        }
        in_chain[root] = true;
        chain.push_back(root);
        /**for (int i = 0; i < static_cast<int>(chain.size()); ++ i) {
            fout << chain[i] << " ";
        }
        fout << "\n";
        for (int i = 0; i < static_cast<int>(edges.size()); ++ i) {
            fout << edges[i] << " ";
        } */
        for (int i = 1; i <= n; ++ i) {
            if (in_chain[i]) {
                dfs_chain(i);
            }
        }
        /**for (int i = 1; i <= n; ++ i) {
            fout << i << ": " << best_length[i] << " " << best_diameter[i] << "\n";
        }*/
        best_left[0] = best_diameter[chain[0]];
        ///fout << best_left[0] << " ";
        for (int i = 1; i < static_cast<int>(chain.size()); ++ i) {
            best_left[i] = max(best_left[i - 1], i + best_length[chain[i]]);
            ///fout << best_left[i] << " ";
        }
        ///fout << "\n";
        best_right[chain.size() - 1] = best_diameter[chain.back()];
        ///fout << best_right[chain.size() - 1] << " ";
        for (int i = chain.size() - 2; i >= 0; -- i) {
            best_right[i] = max(best_right[i + 1], (int)chain.size() - i - 1 + best_length[chain[i]]);
            ///fout << best_right[i] << " ";
        }
        int answer = n;
        for (int i = 1; i < static_cast<int>(chain.size()); ++ i) {
            answer = min(answer, max((best_left[i - 1] + 1) / 2 + 1 + (best_right[i] + 1) / 2, max(best_left[i - 1], best_right[i])));
        }
        cout << answer << "\n";
    }
    return 0;
}