并查集入门题
时间:2019-09-06
本文章向大家介绍并查集入门题,主要包括并查集入门题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
POJ 1611
题意:给你各个集合包含的元素,求0所在的集合总共有多少个不相同的元素。
题解:维护一个size即可,注意size是在什么时候进行相加的。
//#include <bits/stdc++.h> #include <cstdio> using namespace std; int fa[30005], size[30005]; int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } int main() { int n, m; while(~scanf("%d%d", &n, &m)) { if(n==0 && m==0) break; for(int i=0; i<n; i++) fa[i]=i, size[i]=1; for(int i=0; i<m; i++) { int cnt, x, y; scanf("%d", &cnt); if(cnt) scanf("%d", &x); for(int i=1; i<cnt; i++) { scanf("%d", &y); int px=find(x), py=find(y); if(px!=py){ size[px]+=size[py]; fa[py]=px; } } } int p=find(0); printf("%d\n", size[p]); } return 0; }
POJ 1988 cube stacking
题意: 有N(N<=30,000)堆方块,开始每堆都是一个方块,方块编号1 – N. 有两种操作:
• M x y : 表示把方块x所在的堆,拿起来叠放到y所在的堆上。
• C x : 问方块x下面有多少个方块。
• 操作最多有 P (P<=100,000)次。对每次C操作,输出结果
题解:形成一种树形结构,直接用带权并查集维护,size,under 即可。注意路径压缩的过程中别写错了。
//#include <bits/stdc++.h> #include <cstdio> using namespace std; const int maxn=30005; int fa[maxn], under[maxn], size[maxn]; int find(int x) { if(fa[x]==x) return x; int t=find(fa[x]); under[x]+=under[fa[x]]; // 注意是加上under[fa[x]]而不是under[t] return fa[x]=t; } void merge(int x, int y) { int px=find(x), py=find(y); if(px!=py){ under[py]=size[px]; //注意在合并之前,把所有要维护的都维护掉 size[px]+=size[py]; fa[py]=px; } } void init(int n) { for(int i=1; i<=maxn; i++) { size[i]=1; under[i]=0; fa[i]=i; } } int main() { int n; scanf("%d", &n); init(n); for(int i=0; i<n; i++) { char cmd[10]; int x, y; scanf("%s", cmd); if(cmd[0]=='M'){ scanf("%d%d", &x, &y); merge(y, x); } else{ scanf("%d", &x); find(x); //注意要先路径压缩后在直接输出 printf("%d\n", under[x]); } } return 0; }
BZOJ 1202 [HNOI2005] 狡猾的商人
题意:给你多个区间u到v的和为w,问是否会有冲突,每个位置的值可以是负数。
题解:判断时候只有知道了x-y,x-z,才能判断y-z是否冲突。故使用并查集维护区间和,根节点为起点,在同一个并查集内必然可以判断是否冲突。
#include <bits/stdc++.h> int val[105], fa[105], ok; int find(int x) { if(fa[x]==x) return x; int t=find(fa[x]); val[x]+=val[fa[x]]; return fa[x]=t; } void merge(int u, int v, int w) { int pu=find(u), pv=find(v); if(pu!=pv){ val[pv]=-val[v]-w+val[u]; fa[pv]=pu; } else{ if(val[v]-val[u]!=-w) ok=0; } } int main() { int T; for(scanf("%d", &T); T--; ) { int n, m; scanf("%d%d", &n, &m); for(int i=0; i<=n; i++) val[i]=0, fa[i]=i; ok=1; for(int i=0; i<m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); merge(u-1, v, w); //起点往左边移动一位方便计算 } printf("%s\n", ok? "true":"false"); } return 0; }
原文地址:https://www.cnblogs.com/Yokel062/p/11474954.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法