CF160D Edges in MST

news/2025/2/21 20:12:52/文章来源:https://www.cnblogs.com/huangweiliang/p/18730006

前言

这题不需要树剖或 \(\text{Tarjan}\) 等我不会的算法,只需线段树合并即可。

解题思路

首先我们先随便建出一个最小生成树,树边比较难考虑,先考虑非树边。

对于一条非树边,它只可能是情况 \(2\) 或者 \(3\),这点是显然的。

假设这条边连接 \(x\)\(y\),边权为 \(w\),那么它可以被纳入最小生成树,当且仅当 \(x\)\(y\) 这条路径上的最大边权等于 \(w\),因为这样就可以把这条边换上去且不影响连通性。

对于一条树边,它只可能是情况 \(1\) 或者 \(3\),这点也是是显然的。

假设存在一条可以替换它的边连接 \(x\)\(y\),边权为 \(w\),那么成立的条件就是 \(x\)\(y\) 这条路径包含这条树边,且 \(w\) 等于这条树边的边权。

那么我们可以枚举每一条非树边 \((x,y,w)\),将 \(x\)\(y\) 这条路径上的每一条边都尝试更新其最小值为 \(w\),最后判断每一条边的最小值是否等于其边权。这一步可以使用树链剖分,但是我不会,所以线段树合并做法就此诞生!

我们对于每一个点开一个动态开点权值线段树,对于一次操作,在 \(x\)\(y\)\(lca\) 点的对应线段树上的位置减 \(2\),在 \(x\)\(y\) 对应线段树上的位置加 \(1\),最后只要扫一遍整棵树,从下往上合并,并求出每个点最小的 \(> 0\) 的位置判断即可。

代码实现

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;
struct Edge{int x, y, w, id;bool operator < (const Edge A) const {return w < A.w;}
}e[N];
int n, m, fa[N], res, rt[N][19], mx[N][19], dep[N], vis[N], ans[N];
vector<pair<int, int> > v[N];
int find(int x){if(x == fa[x]) return x;return fa[x] = find(fa[x]);
}
void merge(int x, int y){x = find(x), y = find(y);fa[x] = y;
}
void kruskal(){sort(e + 1, e + 1 + m);for(int i = 1; i <= m; i++){if(find(e[i].x) == find(e[i].y)) continue;merge(e[i].x, e[i].y);res += e[i].w, vis[e[i].id] = 1;v[e[i].x].push_back(make_pair(e[i].y, e[i].w));v[e[i].y].push_back(make_pair(e[i].x, e[i].w));}
}
void dfs(int x, int fa){dep[x] = dep[fa] + 1;for(int i = 1; i <= 18; i++){rt[x][i] = rt[rt[x][i - 1]][i - 1];mx[x][i] = max(mx[x][i - 1], mx[rt[x][i - 1]][i - 1]);}for(auto e : v[x]){int y = e.first, w = e.second;if(y == fa) continue;mx[y][0] = w, rt[y][0] = x;dfs(y, x);}
}
pair<int, int> LCA(int x, int y){int maxn = 0;if(dep[x] > dep[y]) swap(x, y);for(int tmp = dep[y] - dep[x], i = 0; tmp; i++, tmp >>= 1)if(tmp & 1){maxn = max(maxn, mx[y][i]);y = rt[y][i];}if(x == y) return make_pair(x, maxn);for(int i = 18; i >= 0; i--){if(rt[x][i] != rt[y][i]){maxn = max(maxn, mx[x][i]);maxn = max(maxn, mx[y][i]);x = rt[x][i];y = rt[y][i];}}maxn = max(maxn, mx[x][0]);maxn = max(maxn, mx[y][0]);return make_pair(rt[x][0], maxn);
}
bool cmp(Edge A, Edge B){return A.id < B.id;
}
int root[N];
struct Segment{int t[N * 20], ls[N * 20], rs[N * 20], cnt;void pushup(int op){t[op] = t[ls[op]] + t[rs[op]];}void update(int l, int r, int &op, int x, int val){if(!op) op = ++cnt;if(l == r){t[op] += val;return;}int mid = (l + r) >> 1;if(mid >= x) update(l, mid, ls[op], x, val);if(mid + 1 <= x) update(mid + 1, r, rs[op], x, val);pushup(op);return;}int merge(int l, int r, int op1, int op2){if(!op1) return op2;if(!op2) return op1;if(l == r){t[op1] += t[op2];return op1;}int mid = (l + r) >> 1;ls[op1] = merge(l, mid, ls[op1], ls[op2]);rs[op1] = merge(mid + 1, r, rs[op1], rs[op2]);pushup(op1);return op1;}int query(int l, int r, int op){if(l == r) return l;int mid = (l + r) >> 1;if(t[ls[op]] > 0) return query(l, mid, ls[op]);else if(t[rs[op]] > 0) return query(mid + 1, r, rs[op]);else return 0; }
}T;
map<pair<int, int>, int> mp;
void dfs1(int x, int fa, int w1){for(auto e : v[x]){int y = e.first, w = e.second;if(y == fa) continue;dfs1(y, x, w);T.merge(1, M - 10, root[x], root[y]);}if(x == 1) return;if(w1 == T.query(1, M - 10, root[x]))mp[make_pair(x, fa)] = mp[make_pair(fa, x)] = 2;else mp[make_pair(x, fa)] = mp[make_pair(fa, x)] = 1;
}
int main(){cin >> n >> m;for(int i = 1; i <= n; i++) fa[i] = i, root[i] = i;T.cnt = n;for(int i = 1; i <= m; i++){int x, y, w;cin >> x >> y >> w;e[i] = Edge{x, y, w, i};}kruskal();dfs(1, 1);sort(e + 1, e + 1 + m, cmp);for(int i = 1; i <= m; i++){if(!vis[i]){auto ow = LCA(e[i].x, e[i].y);int maxn = ow.second, lca = ow.first;if(maxn == e[i].w){T.update(1, M - 10, root[lca], e[i].w, -2);T.update(1, M - 10, root[e[i].x], e[i].w, 1);T.update(1, M - 10, root[e[i].y], e[i].w, 1);ans[i] = 2;}}}dfs1(1, 1, -1);for(int i = 1; i <= m; i++){if(vis[i])ans[i] = mp[make_pair(e[i].x, e[i].y)];if(ans[i] == 0)cout << "none" << endl;else if(ans[i] == 1) cout << "any" << endl;else cout << "at least one" << endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/887770.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

10亿数据,如何做迁移?

前言 某次金融系统迁移项目中,原计划8小时完成的用户数据同步迟迟未能完成。 24小时后监控警报显示:由于全表扫描SELECT * FROM users导致源库CPU几乎熔毁,业务系统被迫停机8小时。 这让我深刻领悟到——10亿条数据不能用蛮力搬运,得用巧劲儿递接! 今天这篇文章,跟大家一…

2025.2.21的模拟赛题“糖果”题解

2025.2.21的模拟赛题“糖果”题解为避免混淆,题目中的 \(X\) 在下文中为大写。 称前 \(k-1\) 次操作成为1号操作,第 \(k\) 次(不含)以后的操作称作2号操作 设 \(f_{x,i,j}\) 表示在 \(x\) 的子树中,1号操作做了 \(i\) 次,2号操作做了 \(j\) 次 限制就是\(X\) 到跟的路径不…

【飞书】Zabbix 7.2 告警与飞书机器人深度联动的全流程

midnight, the sound of a phone buzzing wakes you up abruptly. "又是告警!"你猛地从床上坐起,眼睛酸涩地盯着手机屏幕。作为一名运维工程师,这样的场景几乎成了家常便饭。无论是深夜还是清晨,系统故障总能找到你的联系方式,仿佛在提醒你:科技24小时不眠不休…

Windows平台上Idea、Tomcat、浏览器页面显示乱码问题解决

核心:乱码问题是由于字符编码不一致导致的,所以解决乱码问题的核心概念是统一字符编码。首先我们查看各个平台的字符编码: Windows cmd中输入chcp 命令查看(Windows系统默认字符编码时GBK)936 代表 GBK 65001 代表 UTF-8 注意:通过chcp命令如 chcp 65001 来更改字符编码只…

关于 xrlong 是神的论证

xrlong orz搜索内容搜索结果__________________________________________________________________________________________本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18729881

idea插件+cursor使用技巧

cursorignore配置# Compiled files *.class *.jar *.war# Build directories target/ build/# IDE files .idea/ *.iml .vscode/ .project .classpath .settings/# Logs *.log logs/# Temporary files *.tmp *.bak *.swp# Maven specific .mvn/ mvnw mvnw.cmd# Spring Boot spe…

设计测试用例方法 -经验方法(三种)

1、基于经验的测试技术之错误推测法 错误推测法也叫错误猜测法,就是根据经验猜想,已有的缺陷,测试经验和失败数据等可能有什么问题并依此设计测试用例2、基于经验的测试技术之异常分析法 系统异常分析法就是针对系统有可能存在的异常操作、软硬件缺陷引起的故障进行分析,依…

DeepSeek 即将发布 5 个开源项目;Cartesia Voice Changer:声音转换、克隆和实时语音翻译丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观点 」、「有看点的 活动 」,但内容仅代表编辑…

Spring复习-注解开发

@Component 基本Bean注解,主要是使用注解的方式替代原有xml的 标签及其标签属性的配置使用@Component 注解替代标签使用:再类上使用 @Component(value = "userDao") //若没有配置value,默认使用类名作为beanName public class UserDaoImpl implements UserDao { }…

测试用例编写技巧

一、用例模板 模板1:模板2:模板3:二、用例的来源 (1)公司就有模板 (2)自己设计模板 (3)用例管理工具种导出模板 三、写用例的核心要素 用例编号、用例标题、前置条件、用例步骤,预期结果、优先级(必填) 系统名称、模块名称、用例创建时间、用例类型、实际结果、执行…

利用deepseek,体验ai写代码

vscode利用cline接入火山引擎deepseek,免费体验ai写代码。注册火山引擎,开通deepseek服务进行火山引擎官网https://www.volcengine.com/,进行注册。进入控制台,访问火山方舟在左侧下拉菜单选择开通管理,开通模型,由于我已经开通过R1模型,以DeepSeek-R1-Distill-Qwen-32B…

测试用例编写

模板1:模板2:模板3:二、用例的来源(1)公司就有模板(2)自己设计模板(3)用例管理工具种导出模板三、写用例的核心要素用例编号、用例标题、前置条件、用例步骤,预期结果、优先级(必填)系统名称、模块名称、用例创建时间、用例类型、实际结果、执行时间(非必填项)四…