Codeforces 1850H:The Third Letter 带权并查集
1850H.The Third Letter
Description:
-
个人, 个条件,每次给出两个人 和 一维的位置关系,以距离 表示,其正负表示方位的前后,判断这 个条件是否矛盾。(不同的人可以在横轴上位于同一点)
Analysis:
- 将所有的横轴位置抽象为一个点,用带权并查集维护点与点之间的链接关系。
- 对于一般的并查集来说,可以维护集合内的联通关系,进而求解不同集合之间的问题(如计数等)或判断图的联通性。带权并查集主打一个边权的维护(即额外的信息)。
- 路径压缩是
的重要一环,相当于建立起每个子节点和根节点的直接关系,这便优化了查找效率,无须从某一节点持续向上递归(一旦树退化成了一条链,岂不是寄了!!)
int find(int x) {
if(x != fa[x]) fa[x] = find(fa[x]);
return fa[x];
// return fa[x] = find(fa[x])
}
- 那带权并查集呢?注意,我们要维护的不是题中所给的
,而是要动态维护起每个点到其父节点(在路径压缩下也就是根节点)的 ,这里就产生了对根节点有影响的两个过程:
( )过程:因路径压缩,节点 原来的 更新为根节点,那么 记录的子节点到父节点的距离 也要相应更新为到根节点(也就是新的父节点)- 合并过程:因集合合并,两个集合各自的根节点变为一个大集合的一个根节点,自然而然,其中一个集合要进行权值的更新。
Solution:
int fa[maxn];
ll w[maxn];
int find(int x) {
if(x != fa[x]) {
// 记录原来的父节点,从而记录原来的父节点 t 到根节点的距离w[t]
int t = fa[x];
fa[x] = find(fa[x]);
w[x] += w[t]; // 路径压缩的权值更新
}
return fa[x];
}
void solve() {
int n,m; cin >> n >> m;
// 初始化
for(int i=1;i<=n;i++) {
fa[i] = i; // 我是我的父亲
w[i] = 0; // 到父节点(目前是自己)的距离
}
bool flag = true; // 标记目前是否已经出现矛盾
while(m--) {
int u,v; ll d;
cin >> u >> v >> d;
if(!flag) continue;
int fu = find(u);
int fv = find(v);
if(fu != fv) {
fa[fu] = fv;
w[fu] = d + w[v] - w[u]; //集合合并的权值更新
}
else { // fu == fv 说明二者距离可求,与所给的d比较即可
if(w[u] - w[v] != d) flag = false;
}
}
if(flag) cout << "YES" << endl;
else cout << "NO" << endl;
}
本文来自博客园,作者:Trilliverse,转载请注明原文链接:https://www.cnblogs.com/Trilliverse/p/17605839.html
分类:
Codeforces 刷题记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!