Cod sursa(job #1759826)

Utilizator CataFetoiuFetoiu Catalin CataFetoiu Data 19 septembrie 2016 21:30:46
Problema Revolta Scor 0
Compilator cpp Status done
Runda Arhiva ICPC Marime 2.82 kb
#include<cstdio>
#include<iostream>
#include<string>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<limits.h>
#include<list>
#include<queue>
#include<map>

using namespace std;

typedef pair<int, int> ii;

#define MAX 100100
#define INF 2000000000
#define TRvi(c, it) \
	for(vector<int>::iterator it = c.begin(); it != c.end(); it++)


int V, treeRoot;
vector<vector<int> > tree;
vector<int> realTree;
vector<ii> EdgeList;
int dp[MAX][3]; /* dp for node and parent-direction */
int height[MAX][3];


int diameter(int node, int parent)
{
	//cout << node << " " << parent << endl;
	int direction;
	if(realTree[node] == parent) /* direction is down */
		direction = 0;
	else
		direction = 1;
	if(dp[node][direction] != -1 && direction == 0)
		return dp[node][direction];

	int res = -INF;
	int maxHeight = 0;
	TRvi(tree[node], v)
	{
		int child = *v;
		if(child != parent)
		{
			res = max(res, diameter(child, node));
		}
	}

	if(res == -INF) /* node is leaf */
	{
		height[node][direction] = 1;
		return 0;
	}
	
	int max1 = -1;
	int max2 = -1;
	int dir;
	TRvi(tree[node], v)
	{
		int child = *v;
		if(child != parent)
		{
			if(realTree[child] == node)
				dir = 0;
			else
				dir = 1;
			maxHeight = max(maxHeight, height[child][dir]);
			int num = height[child][dir];
			if(num > max1)
			{
				max2 = max1;
				max1 = num;
			}
			else if(num > max2)
			{
				max2 = num;
			}
		}
	}

	if(max1 != -1 && max2 != -1)
		res = max(res, (max1 + max2));
	else if(max1 != -1)
		res = max1;
	else
		res = max2;
	height[node][direction] = 1 + maxHeight;

	return dp[node][direction] = res;
}

void dfs(int node, int parent)
{
	realTree[node] = parent;
	TRvi(tree[node], v)
	{
		int child = *v;
		if(child != parent)
		{
			dfs(child, node);
		}
	}
}

int minimizeDiameter()
{
	int res = INF;
	for(int i = 0; i < EdgeList.size(); i++)
	{
		int d1, d2;
		ii front = EdgeList[i];
		int u = front.first;
		int v = front.second;
		d1 = diameter(u, v);
		d2 = diameter(v, u);
		
		int removeEdge = -1;
		removeEdge = max(max(d1, d2), (d1+1)/2 + (d2+1)/2 + 1);
		//printf("%d %d\n", u, v);
		//printf("%d %d %d\n", d1, d2, removeEdge);
		res = min(res, removeEdge);
	}

	res = min(res, diameter(treeRoot, -1));
	
	return res;
}
		
	
			
int main()
{
	FILE* fin = freopen("revolta.in", "r", stdin);
	FILE* fout = freopen("revolta.out", "w", stdout);	

	int start, end;
	int T; cin >> T;
	while(T--) {
	cin >> V;
	tree.clear();
	tree.resize(V);
	realTree.assign(V, -1);
	EdgeList.clear();

	memset(dp, -1, sizeof(dp));
	memset(height, -1, sizeof(height));

	for(int i = 0; i < (V-1); i++)
	{
		cin >> start >> end;
		tree[start].push_back(end);
		tree[end].push_back(start);
		EdgeList.push_back(ii(start, end));
	}
	treeRoot = 0;
	dfs(treeRoot, -1);

	
	
	cout << minimizeDiameter() << endl;

	}

	fclose(fin);
	fclose(fout);
	
	
	return 0;	
}