关闭

ccc 2016 s3

53人阅读 评论(0) 收藏 举报
分类:
/* 
把选中的点和它们的lca标记一下,然后考虑标记的点组成的这棵树。答案是:路径长度和 * 2 - 直径
想办法把选中的点和连接它们的点和边弄出来重新建棵树
以一个选中的点作为根,然后dfs,对每一个非选中的点,根据子树是否有选中的点来决定它是否要选
复杂度为 O(n)
*/ 
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

int n, m;
const int maxn = 100000 + 5;
vector<int> g[maxn];
bool node[maxn], vis[maxn];

bool dfs(int i) {
	vis[i] = true;
	for (int k = 0; k < g[i].size(); k++) {
		int t = g[i][k]; 
		if (!vis[t] && dfs(t)) {
			node[i] = true;
		}
	}
	return node[i];
}

int dist(int i) {
	vis[i] = true;
	int temp = 0;
	for (int k = 0; k < g[i].size(); k ++ ) {
		int t = g[i][k];
		if (!vis[t] && node[t]) {
			temp += dist(t) + 1;
		}
	}
	return temp;
}

struct p {
	int num, dis;
	p(int aa, int bb) : num(aa), dis(bb) {}
};

int diameter(int i) {
	queue<int> q;
	q.push(i);
	vis[i] = true;
	int last;
	while (!q.empty()) {
		int k = q.front(); q.pop(); last = k;
		for (int w = 0; w < g[k].size(); w++) {
			int c_node = g[k][w];
			if (!vis[c_node] && node[c_node]) {
				q.push(c_node); vis[c_node] = true;
			}
		}
	}
	memset(vis, false, sizeof(vis));
	queue<p> Q;
	Q.push(p(last, 0)); vis[last] = true;
	int ans = 0;
	while (!Q.empty()) {
		p k = Q.front(); Q.pop(); ans = k.dis;
		for (int w = 0; w < g[k.num].size(); w++) {
			int c_node = g[k.num][w];
			if (!vis[c_node] && node[c_node]) {
				Q.push(p(c_node, k.dis + 1)); vis[c_node] = true;
			}
		}
	}
	return ans;
}

void solve() {
	memset(vis, false, sizeof(vis));
	int i;
	for (i = 0; i < n; i ++ ) if (node[i]) break;
	dfs(i);
	
	memset(vis, false, sizeof(vis));
	int d1 = dist(i);
	
	memset(vis, false, sizeof(vis));
	int d2 = diameter(i);
	
	printf("%d\n", 2 * d1 - d2);
}

void init() {
	memset(node, false, sizeof(node));
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i ++ ) {
		int a; scanf("%d", &a); node[a] = true;
	}
	for (int i = 0; i < n; i ++ ) g[i].clear();
	for (int i = 1; i <= n - 1; i++) {
		int a, b; scanf("%d%d", &a, &b);
		g[a].push_back(b); g[b].push_back(a);
	}
}

int main() {
	init(); solve();
	return 0;
} 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:338次
    • 积分:52
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档