社交网络(并查集)
问题 C: 社交网络
题目描述
在一个社交网络服务(SNS)中,有N个用户,分别用从1到N的数字标记。
在这个SNS中,两个用户可以成为朋友。友谊是双向的;如果用户X是用户Y的朋友,那么用户Y总是用户X的朋友。
目前,在SNS上有M对朋友关系,第i对由用户Ai和Bi组成。
确定以下操作可以执行的最大次数:
操作:选择三个不同的用户 X 、Y和 Z ,使得 X 和 Y 是朋友,Y 和 Z 是朋友,但 X 和 Z不是朋友。让 X 和 Z 成为朋友。
输入
第一行包含两个正整数 N 和 M,表示有 N 个用户,M 对朋友关系
接下来 M 行,每行描述第 i 对朋友关系。
输出
一行一个整数,表示答案。
样例输入
【样例1】 4 3 1 2 2 3 1 4 【样例2】 3 0 【样例3】 10 8 1 2 2 3 3 4 4 5 6 7 7 8 8 9 9 10
样例输出
【样例1】3 【样例2】0 【样例3】12
提示
样例1解释:
三个新的友谊可以如下产生:
- 用户1与用户3成为朋友,用户3是他们的朋友(用户2)的朋友。
- 用户3与用户4成为朋友,用户4是他们的朋友(用户1)的朋友。
- 用户2与用户4成为朋友,用户4是他们的朋友(用户1)的朋友。
不会有四个或更多的新友谊产生。
- 对于 40% 的数据,1 ≤ N ≤ 1000
- 对于 100% 的数据,1 ≤ N ≤ 2*10, 0 ≤ M ≤ 2*10, 1 ≤ Ai < Bi ≤ N 数据保证没有自环。注意,重复的边算一条边。
分析
我们可以证明:对每个连通块,当它不是团(完全图)时,总能找到满足条件的三个点进行操作,并且不断执行操作直到这个连通块变成一个团为止。对于一个有 (k) 个节点的连通块,其完全图边数为
假设该连通块初始时有 (m) 条边,则最多可以“补全”
条边,也就是操作的最大次数。由于不同连通块之间没有路径,操作只能在各自连通块内进行,所以整个图中可以执行的最大操作次数为所有连通块中“缺失边数”的和,即
代码思路就是在并查集的基础上,再维护两个数组,一个cnt[N]
储存节点个数,一个e[N]
储存边的个数,都储存在根节点位置,再维护一个领接表储存边,用来确保边不重复。
代码
#define int long long const int N = 2e5 + 5; int fa[N],e[N],cnt[N]; //分别为并查集根节点,边数,节点数 vector<int> ed[N]; //领接表存边 inline void init(int n) { //初始化 for (int i = 1;i <= n;++i) { fa[i] = i; cnt[i] = 1; } } int find_fa(int x) { //查找,路径压缩 if (fa[x] != x) fa[x] = find_fa(fa[x]); return fa[x]; } inline void merge(int a,int b) { //合并集合 int t = find_fa(a),q = find_fa(b); if (t == q) {e[t]++;return;} //注意,如果两元素在同一个集合,但是边是不重复的,那么边数加一 cnt[t] += cnt[q]; //把b集合的个数加到a集合上 e[t] += e[q]+1; //把b集合的边数加到a集合上 fa[q] = t; //合并 } signed main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); // // freopen("E:/Code/C++/untitled1/input.txt","r",stdin); // freopen("output.txt","w",stdout); int n,m; cin >> n >> m; init(n); for (int i = 0;i < m;++i) { int a,b; cin >> a >> b; //读入边 bool f = false; //标记 for (auto c : ed[a]) if (c == b) {f = true;break;} //检查是否是重边 if (f) continue; //重边跳过 ed[a].emplace_back(b); //记录边 ed[b].emplace_back(a); merge(a,b); } int ans = 0; for (int i = 1;i <= n;++i) { if (i == fa[i]) { //检查有哪些连通块 ans += 1LL*cnt[i]*(cnt[i]-1)/2 - e[i]; //计算结果 } } cout << ans; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理