【拓扑排序】洛谷 P5536 【XR-3】核心城市

【XR-3】核心城市

题目描述

X 国有 \(n\) 座城市,\(n - 1\) 条长度为 \(1\) 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树。

X 国国王决定将 \(k\) 座城市钦定为 X 国的核心城市,这 \(k\) 座城市需满足以下两个条件:

  1. \(k\) 座城市可以通过道路,在不经过其他城市的情况下两两相互到达。
  2. 定义某个非核心城市与这 \(k\) 座核心城市的距离为,这座城市与 \(k\) 座核心城市的距离的最小值。那么所有非核心城市中,与核心城市的距离最大的城市,其与核心城市的距离最小。你需要求出这个最小值。

输入格式

第一行 \(2\) 个正整数 \(n,k\)

接下来 \(n - 1\) 行,每行 \(2\) 个正整数 \(u,v\),表示第 \(u\) 座城市与第 \(v\) 座城市之间有一条长度为 \(1\) 的道路。

数据范围:

  • \(1 \le k < n \le 10 ^ 5\)
  • \(1 \le u,v \le n, u \ne v\),保证城市与道路形成一棵树。

输出格式

一行一个整数,表示答案。

样例 #1

样例输入 #1

6 3
1 2
2 3
2 4
1 5
5 6

样例输出 #1

1

提示

【样例说明】

钦定 \(1,2,5\)\(3\) 座城市为核心城市,这样 \(3,4,6\) 另外 \(3\) 座非核心城市与核心城市的距离均为 \(1\),因此答案为 \(1\)


解析
思路参考:
https://www.luogu.com.cn/article/8zm2qhcz
拓扑排序扩展n-k个非核心城市,每次扩展距离1,当非核心城市的数量>n-k就break。此时扩展距离的最大值就是答案。

C++代码

#include <cstring>
#include <iostream>

using namespace std;

const int N = 1e5 + 10, M = N * 2;

int n, k, res;
int h[N], w[M], e[M], ne[M], idx;
int q[N], in[N], dist[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void topsort()
{
    int hh = 0, tt = -1;
    for (int i = 1; i <= n; i++)
        if (in[i] == 1) q[++tt] = i;

    while (hh <= tt)
    {
        int t = q[hh++];
        if (hh > n - k) break; // 非核心城市数超了n-k就停止
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            dist[j] = dist[t] + 1;
            res = max(res, dist[j]);
            if (--in[j] == 1) q[++tt] = j;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    memset(h, -1, sizeof h);
    cin >> n >> k;
    for (int i = 0; i < n - 1; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
        in[a]++, in[b]++;
    }
    topsort();
    cout << res;
    return 0;
}
posted @ 2025-01-28 10:13  Tshaxz  阅读(32)  评论(0)    收藏  举报
Language: HTML