题意就是在树中确定$K$个点,满足剩下的$N-K$个点中到这$K$个点的最大距离尽可能小。
理解上肯定是确定一个根,这个根是这个图的中心。
可以通过根据结点的高度,从树的外层一层一层往里面剥,那么每次剥的结点一定是队列里比较靠外的,且加进去的点要么和他同层,要么是层数更高的。所以当减到还剩k个点的时候,它的高度就是答案。
#include
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 Depth[MAXN + 13], Num[MAXN + 13];
int BFS(int n, int k)
{
memset(Depth, 0, sizeof(Depth));
queue
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\n", BFS(n, k));
// cout << solve(n, k) << endl;
}
return 0;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章