我们可以发现只有一条路径能只走一次,(就是从出生地到最后遍历的那个点的路径)而其他的路径都需要走两次。
所以我们让这条 “只走一次的路径” 为直径即可使得行走总长度最小。
那么出生地即为树的直径的标号最小的端点。
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,k,u,v,p,ans,ans1,p1,p2,sum;
int a[N],size[N];
bool vis[N];
int cnt,head[N];
struct edge{int next,to;}e[N<<1];
inline void add(int u,int v)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int u,int fa,int dis)
{
if ((dis>ans || dis==ans && u<ans1) && vis[u]) ans=dis,ans1=u,p=u;
for (register int i=head[u]; i; i=e[i].next)
if (e[i].to!=fa) dfs(e[i].to,u,dis+1);
}
void dfs1(int u,int fa)
{
size[u]=(vis[u]==true);
for (register int i=head[u]; i; i=e[i].next)
if (e[i].to!=fa)
{
dfs1(e[i].to,u);
size[u]+=size[e[i].to];
}
}
void dfs2(int u,int fa)
{
for (register int i=head[u]; i; i=e[i].next)
if (e[i].to!=fa && size[e[i].to]) sum++,dfs2(e[i].to,u);
}
int main(){
scanf("%d%d",&n,&k);
for (register int i=1; i<n; ++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
for (register int i=1; i<=k; ++i) scanf("%d",&a[i]),vis[a[i]]=true;
ans1=n+1;
dfs(a[1],0,0);
p1=p;
ans=0; ans1=n+1; dfs(p1,0,0);
p2=p;
if (p1>p2) swap(p1,p2);
printf("%d\n",p1);
dfs1(p1,0);
dfs2(p1,0);
sum<<=1;
sum-=ans;
printf("%d\n",sum);
return 0;
}