0-1 MST CodeForces - 1242B(并查集)

0-1 MST CodeForces - 1242B(并查集)

题意

给出由边权仅为0,1的边连成的完全图中的1-边,求最小生成树。

思路

显然,给出的完全图,在n的范围上跑一遍最小生成树肯定会TLE,那么就得想别的办法来解决这个问题。由于边权只有0,1,所以目标变为了求只由0-边构成的图中连通块的数量。所以通过并查集,每次和已有的连通块比较,如果当前点与已有连通块间的1-边的边数小于已有连通块的点数,那么必有一条0-边将题目相连,于是可以把该点并入连通块,否则新开连通块。

AC代码

#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include<vector> #include<map> using namespace std; #define inf 0x3f3f3f3f #define ll long long vector<int> G[100005],block; int fa[100005],num[100005]; map<int, int> esum; int n, m; int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } void Merge(int x, int y) { int fx = Find(x), fy = Find(y); if (fx == fy)return; fa[fy] = fx; num[fx] += num[fy]; } int main() { int u, v; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) fa[i] = i; for (int i = 0; i < m; i++) { scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } for (int i = 1; i <= n; i++) { num[i] = 1; esum.clear(); for (int j = 0; j < G[i].size(); j++) { int v = G[i][j]; if (v > i) continue; int fv = Find(v); esum[fv]++; } for (int j = 0; j < block.size(); j++) { int fx = Find(block[j]), fy = Find(i); if (fx == fy) continue; if (num[fx] > esum[fx]) { Merge(fx, fy); } } int fx = Find(i); if (fx == i) block.push_back(i); } int ans = 0; for (int i = 1; i <= n; i++) { if (fa[i] == i) ans++; } printf("%d", ans - 1); return 0; }

__EOF__

本文作者waby
本文链接https://www.cnblogs.com/waby/p/15857130.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   waby  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示