1 条题解
-
0
自动搬运
来自洛谷,原作者为

lcjqwq
赠你满天星搬运于
2025-08-24 21:50:54,当前版本为作者最后更新于2018-07-17 17:43:44,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
看了下题解第一篇,为什么要跑三遍kruskal呢?只跑两遍不就好了?
题意:一个图边权为或,求一个生成树使得边权和为。
(这里要注意这里说的边其实是输入中给的边,所以我是用题目中所说的编写代码,但文字题解中我还是用的上面这种更好理解的方式)
这道题是对kruskal算法的一个透彻使用。
题目中说要保留条边,也许你会认为可以随便加,但是有一些边是要必须保留的。这样才能保证图的连通性。
先以边优先做一遍kruskal(就是从小到大排序),把必须要加入的边个数算出。
再做一遍kruskal,先把那些必须加的加入,然后再加边使得达到条,然后就一直加边了。
在上述过程中,有两种无解的情况:
- 图不练通
- 必须要加的边超过
代码:
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #define no_solution printf("no solution\n"); using namespace std; const int MAXN = 20200; const int MAXM = 100100; int n, m, k, fa[MAXN], tot, cnt; struct edge { int u, v, w; }e[MAXM], ans[MAXM]; bool cmp1(edge e1, edge e2) { return e1.w > e2.w; } bool cmp2(edge e1, edge e2) { return e1.w < e2. w; } int find(int x) { if(fa[x] == x) return x; else return fa[x] = find(fa[x]); } bool Union(int x, int y) { x = find(x), y = find(y); if(x == y) return false; fa[x] = y; return true; } void init() { cnt = tot = 0; for(int i = 1; i <= n; i++) fa[i] = i; } void check() { int tmp = find(1); for(int i = 2; i <= n; i++) { int f = find(i); if(f != tmp) { no_solution; exit(0); } tmp = f; } } int main() { scanf("%d%d%d", &n, &m, &k); for(int i = 1; i <= m; i++) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); init(); sort(e + 1, e + m + 1, cmp1); for(int i = 1; i <= m; i++) if(Union(e[i].u, e[i].v) && e[i].w == 0) tot++, e[i].w = -1; if(tot > k) { no_solution; return 0; } check(); init(); sort(e + 1, e + m + 1, cmp2); for(int i = 1; i <= m; i++) { int f1 = find(e[i].u), f2 = find(e[i].v); if(f1 == f2) continue; if(e[i].w == 1 || tot < k) { ans[++cnt] = e[i]; fa[f1] = f2; if(e[i].w < 1) tot++, e[i].w = 0; } } if(tot < k) { no_solution; return 0; } check( ); for(int i = 1; i <= cnt; i++) { if(ans[i].w == -1) ans[i].w = 0; printf("%d %d %d\n", ans[i].u, ans[i].v, ans[i].w); } return 0; }不要试图复制我的代码,你会因为一些奇怪的空格花式CE
- 1
信息
- ID
- 1823
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者