Comet OJ

一、题目

  【XR-3】核心城市

二、分析

  题意就是在树中确定$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;
}
原文地址:https://www.cnblogs.com/dybala21/p/11416712.html