Codeforces 592D Super M

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
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;
}


發佈了230 篇原創文章 · 獲贊 2 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章