一、题目
二、分析
题意就是在树中确定$K$个点,满足剩下的$N-K$个点中到这$K$个点的最大距离尽可能小。
理解上肯定是确定一个根,这个根是这个图的中心。
可以通过根据结点的高度,从树的外层一层一层往里面剥,那么每次剥的结点一定是队列里比较靠外的,且加进去的点要么和他同层,要么是层数更高的。所以当减到还剩k个点的时候,它的高度就是答案。
三、AC代码
#include <bits/stdc++.h> using namespace std; #define ll long long #define Min(a,b) ((a)>(b)?(b):(a)) #define Max(a,b) ((a)>(b)?(a):(b)) const int MAXN = 1e5; vector<int> G[MAXN + 13]; int Depth[MAXN + 13], Num[MAXN + 13]; int BFS(int n, int k) { memset(Depth, 0, sizeof(Depth)); queue<int> que; for(int i = 1; i <= n; i++) { if(G[i].size() == 1) { Depth[i] = 1; que.push(i); } } int last = n; while(!que.empty()) { int u = que.front(); que.pop(); last--; if(last == k) return Depth[u]; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; Num[v]--; if(Num[v] == 1) { Depth[v] = Max(Depth[v], Depth[u] + 1); que.push(v); } } } return 0; } void init(int n) { memset(Num, 0, sizeof(Num)); for(int i = 1; i <= n; i++) { G[i].clear(); } } int main() { //freopen("input.txt", "r", stdin); // freopen("out.txt", "w", stdout); int n, k; while(scanf("%d%d", &n, &k)!=EOF) { int u, v; init(n); for(int i = 1; i < n; i++) { scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); Num[u]++, Num[v]++; } printf("%d ", BFS(n, k)); // cout << solve(n, k) << endl; } return 0; }