一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
Problem - 1133F2 - Codeforces
二、解题报告
1、思路分析
考虑以根节点为割点,会有若干个连通块
连通块的数目为根节点至少要连出去的边,不妨记为mi
如果mi > D,那么无解
如果根节点的度 < D,那么无解
否则先把一定要连出去的边连了,然后再连D - mi条边
然后处理结果即可
2、复杂度
时间复杂度: O(N+M)空间复杂度:O(N+M)
3、代码详解
#include <bits/stdc++.h>
using PII = std::pair<int, int>;
using i64 = long long;const int inf = 1e9;void solve() {int N, M, D;std::cin >> N >> M >> D;std::vector<std::vector<int>> g(N);std::vector<int> p(N, -1);auto find = [&](auto&& self, int x) -> int {return p[x] < 0 ? x : p[x] = self(self, p[x]);};auto merge = [&](int x, int y) -> void {int px = find(find, x), py = find(find, y);if (px == py) return;if (p[px] > p[py]) std::swap(px, py);p[px] += p[py], p[py] = px;};for (int i = 0, u, v; i < M; i ++ ) {std::cin >> u >> v, -- v, -- u;g[u].push_back(v), g[v].push_back(u);}std::vector<bool> vis(N);vis[0] = true;auto dfs1 = [&](auto&& self, int u, int fa) -> void{vis[u] = true;for (int v : g[u]) {if (v == fa || vis[v]) continue;merge(u, v);self(self, v, u);}};std::unordered_set<int> st;for (int v : g[0])if (!vis[v])dfs1(dfs1, v, 0), st.insert(find(find, v));if (st.size() > D || g[0].size() < D) {std::cout << "NO";return;}std::vector<std::array<int, 2>> ans; ans.reserve(N - 1);vis.assign(N, false), vis[0] = true;auto dfs2 = [&](auto&& self, int u, int fa) -> void {vis[u] = true;for (int v : g[u])if (!vis[v] && v != fa)ans.push_back( { u + 1, v + 1 } ), self(self, v, fa);};for (int v : g[0]) if (st.count(find(find, v))) vis[v] = true, ans.push_back( { 1, v + 1 } ), D --, st.erase(find(find, v));for (int v : g[0])if (!vis[v] && D)vis[v] = true, ans.push_back( { 1, v + 1 } ), D --;for (int v : g[0]) if (vis[v]) dfs2(dfs2, v, 0);if (ans.size() + 1 == N) {std::cout << "YES\n";for (auto& [x, y] : ans)std::cout << x << ' ' << y << '\n';}else std::cout << "NO\n";
}int main () {std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0);int _ = 1;// std::cin >> _;while (_ --)solve();return 0;
}