zoukankan      html  css  js  c++  java
  • CodeForces

    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.

    Examples

    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.

    题意:给定一棵大小为N的树,然后给定K个特殊点。现在让你在原树上任选一个点起点,然后从这个起点遍历所有的特殊点,走的最短路程是多少,选择的起点是哪个。如果多个起点满足题意,输出编号最小的那一个。

    思路:假设必须要走的点组成的树大小为M,那么答案为M*2-dis,其中dis是起点和终点的距离。很显然是在所有必须走到的点中找到树的直径。

    如果我们会虚树,那么我们可以很快地求出这棵树:首先把所有特殊点按照DFS序排序,把排序后相邻两点的LCA求出来,把这些LCA耶标记为特殊点,然后除了虚树的根节点,其他特殊点都可以一直向上连边,直到遇到下一个关键点。

    (也有其他直接DFS得到这棵树的。假设多次询问,虚树的优点就显现出来了,特殊点连边的时候不需要把之间的非特殊点加进来,而是通过倍增得到距离,然后得到一颗点数不超过2*K个点的树。

    #include<bits/stdc++.h>
    const int maxn=400010;
    using namespace std;
    int Laxt[maxn],Next[maxn],To[maxn],in[maxn],a[maxn],cnt;
    int vis[maxn],dep[maxn],fa[maxn][18],dis[maxn],S,T,ans,times;
    bool cmp(int x,int y) { return in[x]<in[y]; }
    void add(int u,int v) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; }
    void dfs(int u,int f)
    {
        in[u]=++times; fa[u][0]=f; dep[u]=dep[f]+1;
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]!=f) dfs(To[i],u);
        }
    }
    void dfs2(int u,int f)
    {
        dis[u]=dis[f]+1;
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]!=f) dfs2(To[i],u);
        }
    }
    int LCA(int u,int v)
    {
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=17;i>=0;i--) if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
        if(u==v) return u;
        for(int i=17;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
        return fa[u][0];
    }
    int main()
    {
        int N,M,tot,u,v,i,j;
        scanf("%d%d",&N,&M);
        for(i=1;i<N;i++){
            scanf("%d%d",&u,&v);
            add(u,v); add(v,u);
        }
        dfs(1,0);
        for(i=1;i<=17;i++)
         for(j=1;j<=N;j++)
          fa[j][i]=fa[fa[j][i-1]][i-1];
        for(i=1;i<=M;i++) scanf("%d",&a[i]);
        sort(a+1,a+M+1,cmp); tot=M;
        for(i=2;i<=M;i++) a[++tot]=LCA(a[i-1],a[i]);
        sort(a+1,a+tot+1,cmp);
        tot=unique(a+1,a+tot+1)-(a+1);
        for(i=1;i<=tot;i++) vis[a[i]]=1; //得到关键点 
        memset(Laxt,0,sizeof(Laxt)); cnt=0;
        for(i=1;i<=tot;i++){   //关键点之间连边得到新树 
            u=a[i];
            while(true){
                if(u==a[1]) break;
                ans++;
                add(u,fa[u][0]); add(fa[u][0],u);
                u=fa[u][0];
                if(vis[u]||u==0) break;
            }
        }
        dfs2(a[1],0);   //得到直径 
        for(i=1;i<=tot;i++) if(dis[a[i]]>dis[S]||(dis[a[i]]==dis[S]&&a[i]<S)) S=a[i];
        dis[S]=0;  
        dfs2(S,0);
        for(i=1;i<=tot;i++) if(dis[a[i]]>dis[T]||(dis[a[i]]==dis[T]&&a[i]<T)) T=a[i];
        printf("%d
    %d
    ",min(S,T),ans*2-(dis[T]-1));
        return 0;
    }
  • 相关阅读:
    iOS开发---iPhone SDK 包含哪些东西?
    COS-8文件系统
    COS-7设备管理
    COS-6主存管理
    COS-5资源分配与调度
    COS-4进程及进程管理
    饭卡管理系统学生E-R图
    COS-3OS的用户接口
    COS-2OS结构和硬件支持
    计算机操作系统-1绪论
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9280991.html
Copyright © 2011-2022 走看看