Codeforces
看题目如果直接从如何配对的角度去考虑的话,还是比较困难的。
但是我们不只能从点的角度入手,我们也可以尝试从边的角度入手。
一条边如果要被两个点之间的最短路径经过,那么这两个点一定分别分布在这一条边的两边。
由于我们选择的是最长路径,而任意两个点之间的简单路径只有一条。
那么很容易就可以发现为了使长度最大,一定会使节点较小的一端连接到另一端,那么每一条边的贡献就是两端的较小值了。
原因也很简单,假设我们目前考虑两个点在同一侧,那么它们的距离就是两个点到最近公共祖先的距离,而由于我们只是使用了一条边分开了两部分,那么这一条边一定比这个祖先要远,所以在同一侧连接的收益一定是低于不同侧连接的收益的。
代码非常短:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,a[200005],siz[200005],ans;
vector<int> e[200005];
void dfs(int p,int fa){for(int i:e[p]){if(i==fa)continue;dfs(i,p);siz[p]+=siz[i];}ans+=min(2*k-siz[p],siz[p]);
}
signed main(){cin>>n>>k;for(int i=1;i<=2*k;i++)cin>>a[i],siz[a[i]]=1;for(int i=1,u,v;i<n;i++){cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}dfs(1,0);cout<<ans;return 0;
}