Codeforces 592D. Super M (贪心 + 树的直径)

Description
Ari the monster is not an ordinary monster. She is the hidden identity of Super M, the Byteforces’ superhero. Byteforces is a country that consists of n cities, connected by n - 1 bidirectional roads. Every road connects exactly two distinct cities, and the whole road system is designed in a way that one is able to go from any city to any other city using only the given roads. There are m cities being attacked by humans. So Ari… we meant Super M have to immediately go to each of the cities being attacked to scare those bad humans. Super M can pass from one city to another only using the given roads. Moreover, passing through one road takes her exactly one kron - the time unit used in Byteforces.

However, Super M is not on Byteforces now - she is attending a training camp located in a nearby country Codeforces. Fortunately, there is a special device in Codeforces that allows her to instantly teleport from Codeforces to any city of Byteforces. The way back is too long, so for the purpose of this problem teleportation is used exactly once.

You are to help Super M, by calculating the city in which she should teleport at the beginning in order to end her job in the minimum time (measured in krons). Also, provide her with this time so she can plan her way back to Codeforces.

Input
The first line of the input contains two integers n and m (1 ≤ m ≤ n ≤ 123456) - the number of cities in Byteforces, and the number of cities being attacked respectively.

Then follow n - 1 lines, describing the road system. Each line contains two city numbers u i and v i (1 ≤ u i, v i ≤ n) - the ends of the road i.

The last line contains m distinct integers - numbers of cities being attacked. These numbers are given in no particular order.

Output
First print the number of the city Super M should teleport to. If there are many possible optimal answers, print the one with the lowest city number.

Then print the minimum possible time needed to scare all humans in cities being attacked, measured in Krons.

Note that the correct answer is always unique.

Examples
Input
7 2
1 2
1 3
1 4
3 5
3 6
3 7
2 7
Output
2
3

Input
6 4
1 2
2 3
2 4
4 5
4 6
2 4 5 6
Output
2
4

Solution
树上有m个关键节点,问从哪个点出发,访问所有关键节点的路径和最小

首先我们可以把没必要走到的点去掉,只留下必须得走的点,建新树
容易看出,若需要返回出发点,则总路径长度 = 新树边数*2,是个固定的值
而本题不需要返回出发点,所以最优的方案是从直径的端点出发,沿着直径走,最后停留在另一端点,这样可以少走直径的长度(树上长度最大值)
所以答案 = 新树边数 * 2 - 新树直径

Code

bool f[maxn];
vector<int>Edge[maxn], G[maxn];
int rt, sum;
void dfs1(int u,int fa){
	for(auto v : Edge[u]){
		if(v == fa) continue;
		dfs1(v,u);
		f[u] |= f[v];
	}
}

void build(int n){
	dfs1(rt,-1);
	for(int u = 1;u <= n;++u){
		if(f[u]) sum++;
		for(auto v : Edge[u]){
			if(f[u] && f[v]) {G[u].pb(v);}
		}
	}
}

int st, d;

void dfs2(int u,int fa,int dis){
	// debug2(u,dis);
	if(dis > d){
		d = dis;
		st = u;
	}
	if(dis == d) st = min(st,u);
	for(auto v :G[u]){
		if(v == fa) continue;
		dfs2(v,u,dis+1);
	}
}
void solve(int n){
	build(n);
	int pos = n + 1;
	st = n+1, d = 0;
	dfs2(rt,-1,0);
	pos = min(pos, st);
	dfs2(st,-1,0);
	pos = min(pos,st);
	printf("%d\n%d\n", pos, (sum-1)*2 - d);
}
int main() {
	int n,m;scanf("%d%d",&n,&m);
	for(int i = 1,u,v;i < n;++i){
		scanf("%d%d",&u,&v);
		Edge[u].pb(v);Edge[v].pb(u);
	}
	for(int i = 1,x;i <= m;++i){
		scanf("%d",&x);f[x] = true;
		rt = max(rt,x);
	}
	solve(n);
    return 0;
}
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页