牢记法则,正难则反
我刚开始考虑的是从深度深的地方开始算,但是发现,我们是越找深度越浅,但是深度深的答案会被深度浅的影响,这样思考起来很复杂。
因此如果能找到一个从上面往下找的方法就好了,所以考虑先把所有的都当作工业节点,然后转化n-k为旅游节点
首先,旅游节点肯定不是跳跃的,而是连续的,因此如果当前点不是旅游节点,他的儿子肯定也不可能是,这样想一想就能接受
当我们把一个工业节点转成旅游节点,那么他的贡献就是子树大小-到根的深度,因为原先是工业节点,如果考虑他是旅游节点,他的父亲都已经是旅游节点。因此本来可以增加他的祖先,现在没了
但是现在他的儿子可以通过他,因此就算出贡献度
之后排序即可

#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=4e5+10; const int mod=1e9+7; int h[N],ne[N],e[N],w[N],idx; int son[N]; int d[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int dfs(int u,int fa,int cur){ int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; son[u]+=dfs(j,u,cur+1); } d[u]=son[u]-cur; return son[u]+1; } int main(){ int n,k; cin>>n>>k; int i; vector<int> num; memset(h,-1,sizeof h); for(i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs(1,-1,0); sort(d+1,d+1+n); reverse(d+1,d+1+n); ll ans=0; for(i=1;i<=n-k;i++){ ans+=d[i]; } cout<<ans<<endl; }