NC53074 Forsaken喜欢独一无二的树
题目
题目描述
众所周知,最小生成树是指使图中所有节点连通且边权和最小时的边权子集。
不过最小生成树太简单了,我们现在来思考一个稍微复杂一点的问题。
现在给定一个 个点, 条边的图,每条边 都有一个权值 。定义删除一条边 的代价为 ,并且你可以对这个图执行任意次删边操作。
设这个图的最小生成树权值和为 ,定义一个图的最小生成树是独一无二的当且仅当这个图的边集中没有除最小生成树外的其他子集能满足权值和为 且使得所有点连通。一个图刚开始可能没有独一无二的最小生成树,现在你可以删除一些边,使得剩下的边的最小生成树大小依然为 并且这个图的最小生成树是独一无二的。
现在我们想要知道删除的边的权值和最小是多少?
输入描述
第一行输入为 和 ,表示这个图的点数和边数。
接下来 行,每行三个值 , , ,分别代表每条边的两个端点和边权。
输出描述
一个整数,代表删除的边的最小权值和。
示例1
输入
1 0
输出
0
备注
题解
知识点:枚举,双指针,最小生成树。
最小生成树出现不同解,是因为同一权值的边连接两个已经连通的点。因此我们可以每次把相同权值的边放一起考虑,如果某条边所连两点已经连通,这个条边就是可以删掉的。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 2e5 + 7, M = 2e5 + 7; struct edge { int u, v, w; }e[M]; int fa[N]; int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void merge(int x, int y) { fa[find(x)] = find(y); } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n, m; cin >> n >> m; for (int i = 1;i <= n;i++) fa[i] = i; for (int i = 1;i <= m;i++) { int u, v, w; cin >> u >> v >> w; e[i] = { u,v,w }; } sort(e + 1, e + m + 1, [&](edge a, edge b) {return a.w < b.w;}); int l = 1, r = 1; ll ans = 0; while (l <= m) { while (r <= m) { if (e[r].w != e[l].w) break; r++; } for (int i = l;i < r;i++) if (find(e[i].u) != find(e[i].v)) ans += e[i].w; for (int i = l;i < r;i++) if (find(e[i].u) != find(e[i].v)) ans -= e[i].w, merge(e[i].u, e[i].v); l = r; } cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17021779.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧