CodeForces - 592D Super M 题解

Posted SHYI

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 592D Super M 题解相关的知识,希望对你有一定的参考价值。

题目大意:

  一棵树 n个点 有m个点被标记 求经过所有被标记的点的最短路径的长度以及起点(如有多条输出编号最小的起点)。

思路:

  1.当且仅当一个点本身或其子树中有点被标记时该点在最短的路径上因此,可以将多余的点删去,得到新的一棵树。
  2.不难发现,新树上的边必定被经过一次或两次,而且当只经过一次的边的集合为树的直径时,路径最短。

反思:

  “如有多条输出编号最小的起点”是个坑点,要在最远的点中找出编号最小的当端点。

代码:

 1 #include<cstdio>
 2 #define u v[i]
 3 const int M=250000;
 4 int s,a[M],v[M],hea[M],nex[M];
 5 bool b[M];
 6 
 7 int read()
 8 {
 9     int x=0; char ch=getchar();
10     while (ch<48 || ch>57) ch=getchar();
11     while (ch>47 && ch<58) x=(x<<1)+(x<<3)+ch-48,ch=getchar();
12     return x;
13 }
14 
15 void add(int x,int y) { v[++s]=y,nex[s]=hea[x],hea[x]=s; }
16 
17 void dfs(int x,int p)
18 {
19     for (int i=hea[x];i;i=nex[i])
20         if (u^p) dfs(u,x),b[x]|=b[u];
21 }
22 
23 void DFS(int x,int y,int p)
24 {
25     a[x]=y;
26     for (int i=hea[x];i;i=nex[i])
27         if (b[u] && u^p) DFS(u,y+1,x);
28 }
29 
30 int main()
31 {
32     int n=read(),m=read(),i,x,y;
33     for (i=1;i<n;++i) x=read(),y=read(),add(x,y),add(y,x);
34     for (i=b[y=read()]=1;i<m;++i) b[read()]=1;
35     for (dfs(y,0),a[0]=s=-1,i=1;i<=n;++i) s=s+b[i];
36     for (DFS(y,x=0,0),i=1;i<=n;++i)
37         if (b[i] && a[x]<a[i]) x=i;
38     for (DFS(x,y=0,0),i=1;i<=n;++i)
39         if (b[i] && a[y]<a[i]) y=i;
40     printf("%d\n%d\n",x<y?x:y,s+s-a[y]);
41     return 0;
42 }

 

以上是关于CodeForces - 592D Super M 题解的主要内容,如果未能解决你的问题,请参考以下文章

[CF592D]Super M

CF 592D(Super M-虚树直径)

CF 592D(Super M-虚树直径)

hdu 4417 Super Mario

python super()使用详解

CodeForces Gym-101350M