ABC 288 C - Don't be cycle
题目链接:
题目大意:给定一个简单无向图,要求删除最小的边数(可以不删)使得图中没有环。
每增加一条边,看这条边的端点
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; int p[N]; int find(int x) { if (p[x] == x) return x; return p[x] = find(p[x]); } int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m, ans = 0; cin >> n >> m; for (int i = 1; i <= n; i++) p[i] = i; for (int i = 1; i <= m; i++) { int u, v; cin >> u >> v; if (find(u) == find(v)) ans++; else p[find(u)] = find(v); } cout << ans; return 0; }
另一种思路:要求需要删除的最小边数,我们可以考虑最多可以保留的最大边数。若最多可以保留
假设图中共有
#include <bits/stdc++.h> using i64 = long long; struct DSU { std::vector<int> f, siz; DSU(int n) : f(n), siz(n, 1) { std::iota(f.begin(), f.end(), 0); } int leader(int x) { while (x != f[x]) x = f[x] = f[f[x]]; return x; } bool same(int x, int y) { return leader(x) == leader(y); } bool merge(int x, int y) { x = leader(x); y = leader(y); if (x == y) return false; siz[x] += siz[y]; f[y] = x; return true; }//如果在一个连通块就返回false,否则合并到一个连通块后返回真 int size(int x) { return siz[leader(x)]; } }; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, m; std::cin >> n >> m; int comp = n;//初始时每个点都是一个独立的连通块 DSU dsu(n); for (int i = 0; i < m; i++) { int u, v; std::cin >> u >> v; u--, v--; comp -= dsu.merge(u, v); } std::cout << m - (n - comp) << "\n"; return 0; }
本文作者:pangyou3s
本文链接:https://www.cnblogs.com/pangyou3s/p/18160462
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步