CF700B Connecting Universities

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;
}
posted @ 2025-12-07 12:44  huhangqi  阅读(2)  评论(0)    收藏  举报