codeforces 592 D. Super M

超级M,即怪兽Ari,接到任务要前往Byteforces国家的m个城市驱赶人类。国家由n个城市和n-1条双向道路构成,每个城市都能通过道路到达其他城市。她需要从Codeforces瞬移至Byteforces并以最短时间完成任务。问题求解最佳瞬移城市和最小耗时。输入包括城市数量n、被攻击城市数量m以及道路和攻击城市信息。输出应为最佳瞬移城市编号及最小耗时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D. Super M
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 ui and vi (1 ≤ ui, vi ≤ 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.


这题仔细想一下其实就是求虚树的直径,当时要求字典序最小的直径,所以要求树的中心,然后再求字典序最小。

/*======================================================
# Author: whai
# Last modified: 2015-11-02 15:27
# Filename: d.cpp
======================================================*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>

using namespace std;

#define LL __int64
#define PB push_back
#define P pair<int, int>
#define X first
#define Y second

const int N = 2 * 1e5 + 5;
vector<int> G[N];

int a[N];

bool is_key[N];
int dis[N];
int f[N];
bool used[N];
bool in_r[N];

void dfs(int u, int d, int fa) {
	f[u] = fa;
	dis[u] = d;
	for(int i = 0; i < G[u].size(); ++i) {
		int v = G[u][i];
		if(v == fa) continue;
		dfs(v, d + 1, u);
	}
}

void init() {
	memset(dis, 0, sizeof(dis));
	memset(f, 0, sizeof(f));
}

int get_rt(int rt, int d, int n) {
	init();
	dfs(rt, 0, 0);
	int ret = N;
	for(int i = 1; i <= n; ++i) {
		if(is_key[i] && dis[i] == d) {
			ret = min(ret, i);
		}
	}
	return ret;
}

void gao(int n) {
	init();
	dfs(a[0], 0, 0);
	int maxx = -1;
	int rt = 0;
	for(int i = 1; i <= n; ++i) {
		if(is_key[i]) {
			if(dis[i] > maxx) {
				rt = i;
				maxx = dis[i];
			}
		}
	}
	
	init();
	dfs(rt, 0, 0);
	maxx = 0;
	for(int i = 1; i <= n; ++i) {
		if(is_key[i]) {
			if(dis[i] > maxx) {
				rt = i;
				maxx = dis[i];
			}
		}
	}
	int nxt = rt;

	while(nxt) {
		in_r[nxt] = 1;
		nxt = f[nxt];
	}
	int mid = maxx / 2;

	rt = N;
	if(maxx & 1) {
		int center1, center2;
		for(int i = 1; i <= n; ++i) {
			if(in_r[i] && dis[i] == mid) {
				center1 = i;
			} else if(in_r[i] && dis[i] == mid + 1){
				center2 = i;
			}
		}
		//cout<<center1<<' '<<center2<<' '<<mid<<endl;
		rt = min(rt, get_rt(center1, mid + 1, n));
		rt = min(rt, get_rt(center2, mid + 1, n));
	} else {
		int center;
		for(int i = 1; i <= n; ++i) {
			if(in_r[i] && dis[i] == mid) {
				center = i;
			}
		}
		rt = min(rt, get_rt(center, mid, n));
	}

	cout<<rt<<endl;
	init();
	dfs(rt, 0, 0);
	int sum = 0;
	for(int i = 1; i <= n; ++i) {
		if(is_key[i]) {
			int nxt = i;
			while(used[nxt] == 0 && nxt != 0) {
				++sum;
				used[nxt] = 1;
				nxt = f[nxt];
			}
		}
	}
	cout<<(sum - 1) * 2 - maxx<<endl;
}


int main() {
	int n, m;
	scanf("%d%d", &n, &m);
	
	for(int i = 0; i < n - 1; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		G[u].PB(v);
		G[v].PB(u);
	}

	for(int i = 0; i < m; ++i) {
		scanf("%d", &a[i]);
		is_key[a[i]] = 1;
	}

	gao(n);

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值