专栏文章

[CF2167F] Tree, TREE!!! 题解

CF2167F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min55ylb
此快照首次捕获于
2025/12/01 20:44
3 个月前
此快照最后确认于
2025/12/01 20:44
3 个月前
查看原文
先考虑 uuSrS_r 内需要满足的条件,首先在选择 LCA 时不能选在 uu 子树外的点,否则 LCA 只能为 uu 的祖先。接下来可以强制钦定 uu 被选择,那么只要接下来选的点都在 uu 子树内,LCA 就必然是 uu。于是需要满足 kk 个点能在 uu 子树内选完,即 sizuk\text{siz}_u\ge k
考察 sizu\text{siz}_u 在根变化时会如何变化。令根为 11,得到此时 uu 子树大小 sizu\text{siz}_u
  • rruu 的儿子 vv 的子树内,则 sizu=nsizv\text{siz}'_u=n-\text{siz}_v,一共有 sizv\text{siz}_v 个这样的 rr
  • rruu 的子树外,则 sizu=sizu\text{siz}'_u=\text{siz}_u,一共有 nsizun-\text{siz}_u 个这样的 rr
  • r=ur=u,则 sizu=n\text{siz}'_u=n
于是可以轻松求出 uu 对答案的贡献。
时间复杂度线性。
codeCPP
#include<bits/stdc++.h>
#define pb emplace_back
#define mp make_pair
#define pob pop_back
using namespace std;
typedef long long ll;
const ll maxn=200007,ee=1e18;
ll n,k,siz[maxn],ans;
vector<ll> edge[maxn];
void dfs(ll u,ll fa){
	siz[u]=1;
	for(auto v:edge[u]){
		if(v==fa) continue;
		dfs(v,u),siz[u]+=siz[v];
		ans+=siz[v]*(n-siz[v]>=k);
	}
	ans+=(n-siz[u])*(siz[u]>=k);
}
int main(void){
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	ios::sync_with_stdio(0),cin.tie(0);
	ll T=1; cin>>T;
	for(;T--;){
		for(ll i=1;i<=n;i++) edge[i].clear();
		cin>>n>>k,ans=n;
		for(ll i=1,u,v;i<n;i++){
			cin>>u>>v;
			edge[u].pb(v),edge[v].pb(u);
		}
		dfs(1,0);
		cout<<ans<<"\n";
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...