POJ1182-并查集(拆点??)||带权并查集
来源:互联网 发布:网络剧受众分析论文 编辑:程序博客网 时间:2024/06/02 00:32
这道题可以用带权并查集写,但是我觉得很难想到。。
听说是枚举归纳出权值之间的关系(这种权值关系的对应,就算在路径压缩的时候也是可以的)
书上的代码很好。,
但是我写的有点麻烦。。、
x 为x属于a集合, x+m 属于b集合, x+2*m为c集合。。
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cmath>#include <vector>#include <queue>/*这一道题可以用带权并查集写,但是我感觉让我写是很困难的。。貌似推出那个关系用向量的写法。我觉得我还没达到那个水平。。书上的解法就很好。相当于思维。就是用三个并查集*/using namespace std;const int maxn=150008;int fa[maxn];int find1(int a){ if(a==fa[a]) return a; return fa[a]=find1(fa[a]);}void unite(int a,int b){ int x=find1(a); int y=find1(b); if(x!=y) fa[x]=y;}void init(int m){ for(int i=1;i<=m*3;i++){ fa[i]=i; }}bool same(int a,int b){ if(find1(a)==find1(b)) return true; return false;}int main(){ int m,n; int a,b,c; scanf("%d%d",&m,&n); int ans=0; init(m); for(int i=0;i<n;i++){ scanf("%d%d%d",&c,&a,&b); if(b>m||a>m) { //puts("!"); ans++;} else if(c==1){ if(same(a,b+m)||same(a+m,b+2*m)||same(a+2*m,b)||same(b,a+m)||same(b+m,a+2*m)||same(b+2*m,a)) //其实呢,这6个,前三个任意取一个,后三个任意取一个就行。因为存在一个,其他俩也一定会存在(为啥??加的时候就是这样。。。) { //puts("?"); ans++;} else{ unite(a,b); unite(a+m,b+m); unite(a+2*m,b+2*m); } } else if(c==2){ if(same(a,b)||same(a+m,b+m)||same(a+2*m,b+2*m)||same(b,a+m)||same(b+m,a+2*m)||same(b+2*m,a)) //同理,一个是同类的关系,另一个反吃的关系 { ans++;} else{ unite(a,b+m); unite(a+m,b+2*m); unite(a+2*m,b); } } } printf("%d\n",ans); return 0;}
大佬的带权代码。。感觉很难想到啊qwq
#include <stdio.h> #include <memory.h> #define MAXN 50001 int father[MAXN],rank[MAXN]; void Init(int n) { int i; for(i=1;i<=n;i++) father[i]=i; memset(rank,0,sizeof(rank)); } int Find_Set(int x) { if(x!=father[x]) { int fx=Find_Set(father[x]); rank[x]=(rank[x]+rank[father[x]])%3; //注意 是rank[father[x]]而不是rank[fx] father[x]=fx; } return father[x]; } bool Union(int x,int y,int type) { int fx,fy; fx=Find_Set(x); fy=Find_Set(y); if(fx==fy) { if((rank[y]-rank[x]+3)%3!=type)return true; //这个关系可以通过举例得出 else return false; } father[fy]=fx; rank[fy]=(rank[x]-rank[y]+type+3)%3; // 与上式不同 需仔细归纳 return false; } int main() { freopen("in.txt","r",stdin); int n,k; int sum,i; int d,x,y; scanf("%d %d",&n,&k); //cin>>n>>k; Init(n); sum=0; for(i=0;i<k;i++) { scanf("%d %d %d",&d,&x,&y); //cin>>d>>x>>y; //用cin会超时 if(x>n || y>n ||(x==y && d==2)) sum++; else if(Union(x,y,d-1)) //传d-1 方便关系式的表达 sum++; } printf("%d\n",sum); return 0; }
阅读全文
0 0
- POJ1182-并查集(拆点??)||带权并查集
- poj1182 带权并查集
- poj1182(带权并查集)
- poj1182食物链(带权并查集)
- POJ1182带权并查集
- 带权并查集 poj1182
- poj1182(食物链)----带权并查集
- POJ1182-食物链(带权并查集)
- poj1182 食物链【带权并查集】
- POJ1182 食物链 带权并查集
- POJ1182 食物链 (带权并查集)
- poj1182 食物链 (带权并查集)
- 带权并查集模板(poj1182食物链验证)
- poj1182食物链(带权并查集+路径压缩)
- 食物链 POJ1182(带权并查集)
- poj1182食物链(带权并查集)
- 并查集 poj1182
- POJ1182-并查集
- pandas删除(drop)方法
- [转]caffe中添加C++的自定义新层
- Android Bitmap与byte[]、Bitmap与Drawable相互转化
- JS对象创建常用方式及原理分析
- 使用Mali Graphics Debugger调优Unity程序(Killer示例)
- POJ1182-并查集(拆点??)||带权并查集
- tengxunyun与aliyun的区别
- sql对时间的操作
- shell简单命令
- ”上帝“的数学定义,人工智能智商与等级划分研究最新进展
- 多语言国家与缩写映射表
- 【TensorFlow-windows】(五) CNN(卷积神经网络)对cifar10的识别
- Hi3519V100与Hi3519V101的区别
- 正则表达式