博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
并查集练习2(带权并查集)
阅读量:4578 次
发布时间:2019-06-08

本文共 6451 字,大约阅读时间需要 21 分钟。

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~

(带权并查集)

1 #include
2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 }10 }11 int fin(int x){12 int t;13 if(x==f[x])return x;14 t=f[x];//记录父节点15 f[x]=fin(f[x]);16 r[x]^=r[t];//类别偏移,或r[x]=(r[x]+r[t])%217 return f[x];18 }19 void uni(int x,int y){20 int fx=fin(x);21 int fy=fin(y);22 f[fx]=fy;23 r[fx]=~(r[x]^r[y]);//类别偏移,或r[fx]=(-r[x]+1+r[y]+2)%224 // 关系:fx与fy= fx与x+ x与y + y与fy25 }26 int main(){27 int t,m,a,b;28 char s[3];29 scanf("%d",&t);30 while(t--){31 scanf("%d%d",&n,&m);32 init();33 while(m--){34 scanf("%s%d%d",s,&a,&b);35 if(s[0]=='D') uni(a,b);36 else{37 if(fin(a)!=fin(b)){38 if(n==2) printf("In different gangs.\n");39 else printf("Not sure yet.\n");40 }41 else{42 if(r[a]==r[b])43 printf("In the same gang.\n");44 else printf("In different gangs.\n");45 }46 }47 }48 }49 return 0;50 }
View Code

 

(带权并查集):与上题差不多嗷。

1 #include
2 #include
3 using namespace std; 4 const int N=2001; 5 int f[N]; 6 int r[N]; 7 int n; 8 void init(){ 9 for(int i=1;i<=n;++i){10 f[i]=i; r[i]=0;11 }12 }13 int fin(int x){14 int t;15 if(x==f[x])return x;16 t=f[x];17 f[x]=fin(f[x]);18 r[x]^=r[t];19 return f[x];20 }21 void uni(int x,int y){22 int fx=fin(x);23 int fy=fin(y);24 f[fx]=fy;25 r[fx]=~(r[x]^r[y]);26 }27 int main(){28 int t,m,a,b,k=1,f;29 scanf("%d",&t);30 while(t--){31 scanf("%d%d",&n,&m);32 init();33 f=1;34 while(m--){35 scanf("%d%d",&a,&b);36 if(f&&fin(a)==fin(b)&&r[a]==r[b])f=0;37 else uni(a,b);38 }39 printf("Scenario #%d:\n%s\n\n",k++,f?"No suspicious bugs found!":"Suspicious bugs found!");40 }41 return 0;42 }
View Code

 

(带权并查集):栈顶方块为父节点,r[i]为i到父节点的距离,num[fin(i)]表示包含i的栈的大小,相减即可。

1 #include
2 #include
3 using namespace std; 4 const int N=30001; 5 int f[N],r[N],num[N]; 6 int n; 7 void init(){ 8 for(int i=1;i
View Code

 

(带权并查集)

1 #include
2 #include
3 using namespace std; 4 const int N=50001; 5 int f[N]; 6 int r[N]; 7 int n,cnt; 8 void init(){ 9 for(int i=1;i<=n;++i){10 f[i]=i; r[i]=0;11 }12 }13 int fin(int x){14 int t;15 if(x!=f[x]){16 t=f[x];17 f[x]=fin(f[x]);18 r[x]+=r[t];19 }20 return f[x];21 }22 void uni(int x,int y,int d){23 int fx=fin(x);24 int fy=fin(y);25 if(fx==fy){26 if(r[y]-r[x]!=d) cnt++;27 }28 else{29 f[fy]=fx;30 r[fy]=-r[y]+r[x]+d;31 }32 }33 int main(){34 int m,d,i,a,b;35 while(scanf("%d%d",&n,&m)==2){36 cnt=0;37 init();38 while(m--){39 scanf("%d%d%d",&a,&b,&d);40 uni(a,b,d);41 }42 printf("%d\n",cnt);43 }44 return 0;45 }
View Code

 

(带权并查集)与上题差不多耶。

1 #include
2 #include
3 using namespace std; 4 const int N=200001; 5 int f[N]; 6 int r[N];//表示与父节点之间的和 7 int n,cnt; 8 void init(){ 9 for(int i=0;i<=n;++i){10 f[i]=i; r[i]=0;11 }12 }13 int fin(int x){14 int t;15 if(x!=f[x]){16 t=f[x];17 f[x]=fin(f[x]);18 r[x]+=r[t];19 }20 return f[x];21 }22 void uni(int x,int y,int d){23 int fx=fin(x);24 int fy=fin(y);25 if(fx==fy){26 if(r[y]-r[x]!=d) cnt++;27 }28 else{29 f[fy]=fx;30 r[fy]=-r[y]+r[x]+d;31 }32 }33 int main(){34 int m,d,i,a,b;35 while(scanf("%d%d",&n,&m)==2){36 cnt=0;37 init();38 while(m--){39 scanf("%d%d%d",&a,&b,&d);40 uni(a-1,b,d);41 }42 printf("%d\n",cnt);43 }44 return 0;45 }
View Code

 

 (带权并查集)经典吖orz.

1 #include
2 #include
3 using namespace std; 4 const int N=50001; 5 int f[N]; 6 int r[N];//表示与父节点的关系,0表示同类,1表示被吃,2表示吃父节点 7 int n,ans; 8 void init(){ 9 for(int i=1;i<=n;++i){10 f[i]=i; r[i]=0;11 }12 }13 int fin(int x){14 int t;15 if(x!=f[x]){16 t=f[x];17 f[x]=fin(f[x]);18 r[x]=(r[x]+r[t])%3;19 }20 return f[x];21 }22 void uni(int x,int y,int d){23 int fx=fin(x);24 int fy=fin(y);25 if(fx==fy){26 if((r[x]-r[y]+3)%3!=d) ans++;27 }28 else{29 f[fx]=fy;30 r[fx]=(-r[x]+d+r[y]+3)%3;31 }32 }33 int main(){34 int m,a,b,d;35 scanf("%d%d",&n,&m);36 init();37 ans=0;38 while(m--){39 scanf("%d%d%d",&d,&a,&b);40 if(a>n||b>n||(d==2&&a==b))ans++;//假话:a或b都大于n,或a吃a41 else uni(a,b,d-1);42 }43 printf("%d\n",ans);44 return 0;45 }
View Code

 

(带权并查集,枚举)石头剪刀布的游戏,并查集部分和上题食物链很像哦。枚举每个小孩为裁判时的情况,再并查集判断。

1 #include
2 #include
3 #include
4 using namespace std; 5 const int N=501; 6 const int M=2001; 7 int f[N],r[N]; 8 int n; 9 void init(){10 for(int i=0;i
')D[i]=1;46 else D[i]=2;47 }48 cnt=ans=id=0;49 for(i=0;i
ans) ans=j;//取最大的矛盾轮数57 break;58 }59 }60 }61 if(!flag){ id=i; cnt++;}62 }63 if(cnt==0) puts("Impossible");64 else if(cnt==1)65 printf("Player %d can be determined to be the judge after %d lines\n",id,ans);66 else puts("Can not determine");67 }68 return 0;69 }
View Code

 

(带权并查集,离散化)

题意:有一个已知长度的01串,给出多个区间[l,r],并知道区间中1的个数是奇数还是偶数,问前几个区间互不矛盾。

离散化hash暂时还不会,先用map映射处理大数据问题吧。。

1 #include
2 #include
3 using namespace std; 4 const int N=5001; 5 int f[N]; 6 int r[N];//表示到父节点的1的个数的奇偶性,0表示偶数个1,1表示奇数个1 7 int n; 8 void init(){ 9 for(int i=0;i
p;39 flag=1;40 k=0;41 ans=m;42 for(i=0;i
View Code

 

写完随笔怎么突然有种很萌比的感觉。。。下个月的今天再复习一下好啦。。

转载于:https://www.cnblogs.com/GraceSkyer/p/5769014.html

你可能感兴趣的文章
查找不同的木棍
查看>>
面试题:顺时针打印矩阵
查看>>
DataSet、DataTable、DataRow、DataColumn区别及使用实例
查看>>
python 特殊方法
查看>>
Python3 练习笔记四
查看>>
装箱问题
查看>>
Android线程管理(一)——线程通信
查看>>
linux内核开源代码地址下载
查看>>
window.open打开新窗口 参数
查看>>
kuangbin专题 专题二 搜索进阶 哈密顿绕行世界问题 HDU - 2181
查看>>
目前主流的四大浏览器内核
查看>>
js数组遍历的常用的几种方法以及差异和性能优化
查看>>
将ftp目录映射为本地盘符
查看>>
Python中os与sys模块的区别
查看>>
AngularJS 通过 ocLazyLoad 实现动态(懒)加载模块和依赖
查看>>
代理模式学习笔记
查看>>
lnmp环境的nginx的tp5配置
查看>>
前端吐槽的后端接口那些事
查看>>
STM32 使用 FreeRTOS过程记录
查看>>
每日英语:Lost Inheritance
查看>>