Cod sursa(job #1708369)

Utilizator stefanrStefan Ruseti stefanr Data 26 mai 2016 22:51:14
Problema Revolta Scor Ascuns
Compilator cpp Status done
Runda Marime 5.58 kb

/* 
 * File:   brute.cpp
 * Author: Stefan
 *
 * Created on May 23, 2016, 11:48 PM
 */

#include <cstdlib>
#include <iostream>
#include <vector>

using namespace std;

#define INF 100000000
#define NMAX 10000

int n;
vector< vector<int> > graph;
vector<int> dhl;
vector<int> dl;
vector<bool> visited;
int removedFirst, removedSecond;
int addedFirst, addedSecond;


bool removed(int a, int b) {
    if (removedFirst == -1) return false;
    return (a == removedFirst && b == removedSecond) || 
           (b == removedFirst && a == removedSecond); 
}

int computeDepth(int node) {
    visited[node] = true;
    dhl[node] = 0;
    for (vector<int>::iterator next = graph[node].begin(); next < graph[node].end(); next++) {
        if (!visited[*next] && !removed(node, *next)) {
            int d = computeDepth(*next);
            if (dhl[node] < d) dhl[node] = d; 
        }
    }
    dhl[node] ++;
    return dhl[node];
}

int moveRoot(int node) {
    int a = 0;
    int b = 0;
    int longest = -1;
    for (vector<int>::iterator next = graph[node].begin(); next < graph[node].end(); next++) {
        if (!removed(node, *next)) {
            int d = dhl[*next];
            if (d > a) {
                b = a;
                a = d;
                longest = *next;
            }
            else
                if (d > b) b = d;
        }
    }
    //cout << a << " " << b << " " << longest << endl;
    if (longest == -1 || a - b <= 1) return node;
    dhl[node] = b + 1;
    return moveRoot(longest);
}

void dfs(int node) {
    int maxDepth1 = 0, maxDepth2 = 0;
    int maxDiam1 = 0, maxDiam2 = 0;
    visited[node] = true;
    for (int i = 0; i < graph[node].size(); i++) {
        int next = graph[node][i];
        if (!visited[next] && !removed(node, next)) {
            dfs(next);
            if (dhl[next] > maxDepth1) {
                maxDepth2 = maxDepth1;
                maxDepth1 = dhl[next];
            }
            else {
                if (dhl[next] > maxDepth2) {
                    maxDepth2 = dhl[next];
                }
            }
            if (dl[next] > maxDiam1) {
                maxDiam2 = maxDiam1;
                maxDiam1 = dl[next];
            }
            else {
                if (dl[next] > maxDiam2) {
                    maxDiam2 = dl[next];
                }
            }
        }
    }
    dhl[node] = maxDepth1 + 1;
    dl[node] = max(maxDiam1, maxDepth1 + maxDepth2);
}

int diameter() {
    visited.assign(n, false);
    dhl.assign(n, 0);
    dl.assign(n, 0);
    dfs(0);
    for (int i = 0; i < n; i++)
        if (!visited[i]) return -1;
    return dl[0];
}

void clear() {
    graph.clear();
    dhl.clear();
    dl.clear();
    visited.clear();
}

vector< pair<int,int> > getEdges() {
    vector< pair<int,int> > result;
    for (int i = 0; i < n - 1; i ++) {
        for (vector<int>::iterator next = graph[i].begin(); next < graph[i].end(); next++) {
            if (i > *next) continue;
            result.push_back(pair<int, int>(i, *next));
        }
    }
    return result;
}

vector< pair<int,int> > getInexistentEdges() {
    vector< pair<int,int> > result;
    vector<bool> exists(n, false);
    for (int i = 0; i < n - 1; i ++) {
        exists.assign(n, false);
        for (vector<int>::iterator next = graph[i].begin(); next < graph[i].end(); next++) {
            exists[*next] = true;
        }
        for (int j = i + 1; j < n; j++)
            if (!exists[j]) 
                result.push_back(pair<int, int>(i, j));
               
    }
    return result;
}

bool better(int *best, int *guess) {
    for (int i = 0; i < 4; i++) {
        if (guess[i] == best[i]) continue;
        return guess[i] < best[i];
    }
    return false;
}
/*
 * 
 */
int main(int argc, char** argv) {

    freopen ("revolta.in","r",stdin);
    freopen ("revolta.out","w",stdout);
    int t;
    scanf("%d", &t);
    while (t-- > 0) {
        scanf("%d", &n);
        graph.assign(n, vector<int>());
        dl.assign(n, -1);
        dhl.assign(n, -1);
        removedFirst = -1;
        int a, b;
        for (int i = 0; i < n - 1; i++) {
            scanf("%d &d", &a, &b);
            graph[a].push_back(b);
            graph[b].push_back(a);
        }
        int initialDiameter = diameter();
        vector< pair<int,int> > edges = getEdges();
        vector< pair<int,int> > possibleEdges = getInexistentEdges();
        int best = n;
        int bestSoFar[4];
        int guess[4];
        for (int i = 0; i < edges.size(); i++) {
            removedFirst = edges[i].first;
            removedSecond = edges[i].second;
            for (int j = 0; j < possibleEdges.size(); j++) {
                pair<int, int> e = possibleEdges[j];
                graph[e.first].push_back(e.second);
                graph[e.second].push_back(e.first);
                int d = diameter();
                graph[e.first].pop_back();
                graph[e.second].pop_back();
                if (d == -1) continue; //not a tree
                guess[0] = e.first;
                guess[1] = e.second;
                guess[2] = removedFirst;
                guess[3] = removedSecond;
                if ((d == best && better(bestSoFar, guess)) || d < best) {
                    for (int g = 0; g < 4; g++) {
                        bestSoFar[g] = guess[g];
                    }
                    best = d;
                }
            }
        }
        if (initialDiameter <= best) cout << initialDiameter << endl;
        else {
            cout << best << endl;
            //cout << bestSoFar[2] << " " << bestSoFar[3] << endl;
            //cout << bestSoFar[0] << " " << bestSoFar[1] << endl;
        }
        clear();

    }
    return 0;
}