Codeforces 592D Super M
2015-11-01 12:31
441 查看
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 roadi.
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.
Sample test(s)
input
output
input
output
Note
In the first sample, there are two possibilities to finish the Super M's job in 3 krons. They are:
and
.
However, you should choose the first one as it starts in the city with the lower number.
解题思路:本题题意为给定一棵树,然后标记树上的m个点,问从哪个点出发走完所有被标记的点走过的边数最少,这题貌似之前在什么地方做过。
首先我们求解的对象便是在包含所有的被标记点的最小子树上进行移动,其余多余的边我们是没有必要走的。我们便以这棵子树为基础,假设从这棵子树上的某一点出发,遍历完所有的点之后回到该点需要走的边数是个固定值为这棵子树的边数的两倍,因为走过去还要走回来所以每条边均被走了两遍,但是根据我们题目的要求,其实遍历的最后一个点是没有必要返回的,答案应该为边数的两倍减去这两点之间的距离,要使结果最优,必然要使这两点之间的距离尽可能的大,书上两点之间的距离的最大值便为树的直径,因此我们最终要求解的问题便转换成求解这棵子树并且这棵子树的直径。代码如下:
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
const int maxn = 123456 + 100;
struct Edge {
int v, next;
Edge() { }
Edge(int t_v, int t_next) : v(t_v), next(t_next) { }
}edges[2*maxn];
int head[maxn], edge_sum;
void init_graph() {
edge_sum = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v) {
edges[edge_sum].v = v;
edges[edge_sum].next = head[u];
head[u] = edge_sum++;
edges[edge_sum].v = u;
edges[edge_sum].next = head[v];
head[v] = edge_sum++;
}
bool mark[maxn];
int d[maxn];
bool in_new[maxn];
void dfs(int u, int p) {
if(p != -1) {
d[u] = d[p] + 1;
}
if(mark[u]) in_new[u] = true;
for(int i = head[u]; i != -1; i = edges[i].next) {
int v = edges[i].v;
if(v == p) continue;
dfs(v, u);
in_new[u] |= in_new[v];
}
return ;
}
int main() {
//freopen("aa.in", "r", stdin);
int n, m, u, v;
int e_num = 0;
init_graph();
scanf("%d %d", &n, &m);
for(int i = 1; i < n; ++i) {
scanf("%d %d", &u, &v);
add_edge(u, v);
}
memset(mark, false, sizeof(mark));
for(int i = 1; i <= m; ++i) {
scanf("%d", &u);
mark[u] = true;
}
memset(d, 0, sizeof(d));
memset(in_new, false, sizeof(in_new));
int maxd, vt1, vt2;
for(int i = 1; i <= n; ++i) {
if(mark[i]) {
maxd = 0;
vt1 = i;
dfs(i, -1);
break;
}
}
for(int i = 1; i <= n; ++i) {
if(in_new[i]) {
e_num++;
}
if(mark[i]) {
if(d[i] > maxd) {
maxd = d[i];
vt1 = i;
}
}
}
e_num = 2 * (e_num - 1);
memset(d, 0, sizeof(d));
dfs(vt1, -1);
maxd = 0;
vt2 = vt1;
for(int i = 1; i <= n; ++i) {
if(mark[i]) {
if(d[i] > maxd) {
maxd = d[i];
vt2 = i;
}
}
}
printf("%d\n", min(vt1, vt2));
printf("%d\n", e_num - maxd);
return 0;
}
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 roadi.
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.
Sample test(s)
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
Note
In the first sample, there are two possibilities to finish the Super M's job in 3 krons. They are:
and
.
However, you should choose the first one as it starts in the city with the lower number.
解题思路:本题题意为给定一棵树,然后标记树上的m个点,问从哪个点出发走完所有被标记的点走过的边数最少,这题貌似之前在什么地方做过。
首先我们求解的对象便是在包含所有的被标记点的最小子树上进行移动,其余多余的边我们是没有必要走的。我们便以这棵子树为基础,假设从这棵子树上的某一点出发,遍历完所有的点之后回到该点需要走的边数是个固定值为这棵子树的边数的两倍,因为走过去还要走回来所以每条边均被走了两遍,但是根据我们题目的要求,其实遍历的最后一个点是没有必要返回的,答案应该为边数的两倍减去这两点之间的距离,要使结果最优,必然要使这两点之间的距离尽可能的大,书上两点之间的距离的最大值便为树的直径,因此我们最终要求解的问题便转换成求解这棵子树并且这棵子树的直径。代码如下:
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
const int maxn = 123456 + 100;
struct Edge {
int v, next;
Edge() { }
Edge(int t_v, int t_next) : v(t_v), next(t_next) { }
}edges[2*maxn];
int head[maxn], edge_sum;
void init_graph() {
edge_sum = 0;
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v) {
edges[edge_sum].v = v;
edges[edge_sum].next = head[u];
head[u] = edge_sum++;
edges[edge_sum].v = u;
edges[edge_sum].next = head[v];
head[v] = edge_sum++;
}
bool mark[maxn];
int d[maxn];
bool in_new[maxn];
void dfs(int u, int p) {
if(p != -1) {
d[u] = d[p] + 1;
}
if(mark[u]) in_new[u] = true;
for(int i = head[u]; i != -1; i = edges[i].next) {
int v = edges[i].v;
if(v == p) continue;
dfs(v, u);
in_new[u] |= in_new[v];
}
return ;
}
int main() {
//freopen("aa.in", "r", stdin);
int n, m, u, v;
int e_num = 0;
init_graph();
scanf("%d %d", &n, &m);
for(int i = 1; i < n; ++i) {
scanf("%d %d", &u, &v);
add_edge(u, v);
}
memset(mark, false, sizeof(mark));
for(int i = 1; i <= m; ++i) {
scanf("%d", &u);
mark[u] = true;
}
memset(d, 0, sizeof(d));
memset(in_new, false, sizeof(in_new));
int maxd, vt1, vt2;
for(int i = 1; i <= n; ++i) {
if(mark[i]) {
maxd = 0;
vt1 = i;
dfs(i, -1);
break;
}
}
for(int i = 1; i <= n; ++i) {
if(in_new[i]) {
e_num++;
}
if(mark[i]) {
if(d[i] > maxd) {
maxd = d[i];
vt1 = i;
}
}
}
e_num = 2 * (e_num - 1);
memset(d, 0, sizeof(d));
dfs(vt1, -1);
maxd = 0;
vt2 = vt1;
for(int i = 1; i <= n; ++i) {
if(mark[i]) {
if(d[i] > maxd) {
maxd = d[i];
vt2 = i;
}
}
}
printf("%d\n", min(vt1, vt2));
printf("%d\n", e_num - maxd);
return 0;
}
相关文章推荐
- hdu acm 1863 畅通工程
- ThinkPHP中数据库CRUD操作方法盘点(limit、page、table、order、data方法)
- 跟着猫哥学Golang[5] - 循环
- S3C2416裸机开发系列二二_Lwip的移植
- php Redis存储Session
- Tomcat7单机多实例部署(windows版)
- 没有堕落的科学,只有堕落的科学家
- 第9周项目4-广义表算法库及应用(2)
- ArrayAdapter
- 【简单题】CCPC Huatuo's Medicine L
- 极限学习机(Extreme Learning Machine)概述
- 杭电1114--完全背包
- hdu4933 Miaomiao's Function
- 使用U盘启动安装操作系统的一些心得
- 新版百元纸币下月发行!这些防伪你要知道
- Java中的Class类
- 一个介绍linux的博客
- JAVA connectFour
- java的Constructor和static块
- HDFS 恢复某时刻删除的文件