思路:拓扑从叶子结点往里推出非核心
#include<bits/stdc++.h>
using namespace std;
queue<int>q;
bool v[100005];//存v[i]表示i是否如果队
int h[100005];//前向星
int num[100005];//num[i]表示连接到i的边数,num[i]为1就是叶子结点
int ans[100005];//存点权
struct edg{
int to,nxt;
};
edg line[200005];
int cnt,mxs;//mxs存答案(最大值)
void link(int x,int y){
line[++cnt].nxt=h[x];
h[x]=cnt;
line[cnt].to=y;
num[x]++;
}//链式前向星
int main(){
int n,k;
cin>>n>>k;
int i;
for (i=1;i<n;i++){
int x,y;
cin>>x>>y;
link(x,y);
link(y,x);
} //建边
for (i=1;i<=n;i++){
if (num[i]==1){
q.push(i);
ans[i]=1;
v[i]=1;
}
}//叶子结点入队
int tot=0;//tot表示已选的非核心城市
while (tot<n-k){//共需要n-k个非核心城市
int x=q.front();
q.pop();
tot++;//将x选为非核心城市
for (i=h[x];i;i=line[i].nxt){
if (!v[line[i].to]){
ans[line[i].to]=ans[x]+1;//点权
q.push(line[i].to);
v[line[i].to]=1;
}
}//x的临点入队
}
while (q.size()){
int x=q.front();
q.pop();
ans[x]=0;
}//把没有用到的点权归零
for (i=1;i<=n;i++){
mxs=max(mxs,ans[i]);
}//取最大值
cout<<mxs;
}