社区讨论

警惕Kruskal重构树的未定义行为

学术版参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mlisbl5h
此快照首次捕获于
2026/02/12 09:33
上周
此快照最后确认于
2026/02/14 13:50
5 天前
查看原帖

正确代码

CPP
void Kruskal() {
	for(int i = 1; i <= n; i ++)
		fa[i] = i;
	vector<int> vec(m);
	iota(vec.begin(), vec.end(), 1);
	sort(vec.begin(), vec.end(), [](int x, int y) {
		return w[x] > w[y];
	});
	for(int i : vec) {
		if(find(u[i]) == find(v[i])) continue;
		val[++n] = w[i]; fa[n] = n;
		G[n].push_back(find(u[i])), G[n].push_back(find(v[i]));
		fa[find(u[i])] = fa[find(v[i])] = n;
	}
}

错误代码

CPP
void kru() {
    for(int i = 1;i <= n;i++)
        fa[i] = i;
    sort(ro + 1 , ro + m + 1 , cmp);
    
    for(int i = 1;i <= m;i++) {
        int fu = find(ro[i].u), fv = find(ro[i].v);
        if(fu == fv) continue;
        
        fa[++n] = n;
        val[n] = ro[i].w;
        G[n].push_back(fu);
        G[n].push_back(fv);
        fa[fu] = n;
        fa[fv] = n;
    }
}

注意这一行
CPP
 fa[++n] = n;
 val[n] = ro[i].w;
表面和上面代码本质上一致
实际上是 UB 详见 https://www.luogu.com.cn/discuss/1247785?page=2 希望大家不要重蹈覆辙

回复

0 条回复,欢迎继续交流。

正在加载回复...