cf592d
2015-11-03 23:31
323 查看
题意:给出一个无根树,点数为10^5,所有边的长度为1。给定其中有一些点是受到攻击的。
现在要求一个人选定一个点作为起点,走遍所有的受攻击点(不用再回到起点)。
需要的最短距离是多少,选定的起点是哪个。
分析:这是一个求树直径的变形题,原版请看这里。
求树的直径即树中最远的点对,需要进行两次bfs或者dfs。这里我们用的是dfs。
首先我们假设所有点都受到攻击,那么要走完所有点再回到起点,路程L就是树上所有边的长度和乘以2。
不用回到起点遍历所有点的最短距离就是用这个L减去树上的最远两点之间的距离。
我们要把起点选在最远点对中的点才能保证所得解最小。
但本题中不是所有点都受到攻击,所以在求最远点对的时候要进行一些改变。要找最远的受攻击点对。
首先要以一个受攻击点为根(这个是本题最大难点,不太容易想到),进行第一次dfs,找到最深的受攻击点之后,再以它为根找最深的受攻击点。(注意长度相同时,找编号最小的)
再求出以任意受攻击点为根,遍历所有受攻击点的路程和。两者相减即为解。
View Code
现在要求一个人选定一个点作为起点,走遍所有的受攻击点(不用再回到起点)。
需要的最短距离是多少,选定的起点是哪个。
分析:这是一个求树直径的变形题,原版请看这里。
求树的直径即树中最远的点对,需要进行两次bfs或者dfs。这里我们用的是dfs。
首先我们假设所有点都受到攻击,那么要走完所有点再回到起点,路程L就是树上所有边的长度和乘以2。
不用回到起点遍历所有点的最短距离就是用这个L减去树上的最远两点之间的距离。
我们要把起点选在最远点对中的点才能保证所得解最小。
但本题中不是所有点都受到攻击,所以在求最远点对的时候要进行一些改变。要找最远的受攻击点对。
首先要以一个受攻击点为根(这个是本题最大难点,不太容易想到),进行第一次dfs,找到最深的受攻击点之后,再以它为根找最深的受攻击点。(注意长度相同时,找编号最小的)
再求出以任意受攻击点为根,遍历所有受攻击点的路程和。两者相减即为解。
#include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = (int)(2e5) + 20; int n, m; int root; vector<int> g[MAX_N]; bool attacked[MAX_N]; int depth[MAX_N]; long long path_len; void input() { scanf("%d%d", &n, &m); for (int i = 0; i < n - 1; i++) { int a, b; scanf("%d%d", &a, &b); a--; b--; g[a].push_back(b); g[b].push_back(a); } memset(attacked, 0, sizeof(attacked)); for (int i = 0; i < m; i++) { int a; scanf("%d", &a); a--; attacked[a] = true; } } void dfs(int u, int father) { for (int i = 0; i < (int)g[u].size(); i++) { int v = g[u][i]; if (v == father) continue; depth[v] = depth[u] + 1; dfs(v, u); } } int find_next() { int ret = root; for (int i = 0; i < n; i++) { if (!attacked[i]) continue; if (depth[i] > depth[ret] || (depth[i] == depth[ret] && i < ret)) { ret = i; } } return ret; } bool cal_depth(int u, int father) { bool ret = false; for (int i = 0; i < (int)g[u].size(); i++) { int v = g[u][i]; if (v == father) continue; if (!cal_depth(v, u)) continue; path_len += 2; ret = true; } return ret || attacked[u]; } int main() { input(); root = find(attacked, attacked + n, true) - attacked; depth[root] = 0; dfs(root, -1); root = find_next(); depth[root] = 0; dfs(root, -1); int end = find_next(); int city = min(root, end); path_len = 0; cal_depth(root, -1); printf("%d\n%I64d\n", city + 1, path_len - depth[end]); return 0; }
View Code
相关文章推荐
- coredata 详解
- Qt在线安装
- 软件测试简介、测试原则、测试过程、测试内容、测试方法
- 分成互质组
- 数据结构_树形结构_二叉树
- UGUI事件解析
- python3 与 python2的 区别比较
- 关于内存对齐
- hive 建表例子
- Spring+Mybatis+Mysql搭建分布式数据库访问框架
- DirectX 3D纹理
- 深入解析单例模式
- HDU 3435 A new Graph Game (KM)
- Oracle Exception In Loop
- leetcode-Sliding Window Maximum
- HighCharts 曲线
- 家庭作业
- [Data Structure] 闭散列的设计问题
- (Alpha)Let's-技术文档(技术规格说明书)
- LAMP环境安装