BZOJ1202 [HNOI2005]狡猾的商人(并查集)
2015-06-29 13:45
344 查看
【题解】
给出[l,r]的区间和,相当于s[r]-s[l](前缀和思想)
一旦已经知道了 s[a]-s[b],s[b]-s[c],再给出一条[a,c]就可以判断"账本的真假"了
将每条这样的信息(l,r,w),l,r放入一个集合中,用并查集来维护,并维护cha[l]=s[root]-s[l],cha[r]=s[root]-s[r]
若 l,r已经在同一个集合中,就直接查询cha[l]-cha[r],判读与w是否相等
【代码】
给出[l,r]的区间和,相当于s[r]-s[l](前缀和思想)
一旦已经知道了 s[a]-s[b],s[b]-s[c],再给出一条[a,c]就可以判断"账本的真假"了
将每条这样的信息(l,r,w),l,r放入一个集合中,用并查集来维护,并维护cha[l]=s[root]-s[l],cha[r]=s[root]-s[r]
若 l,r已经在同一个集合中,就直接查询cha[l]-cha[r],判读与w是否相等
【代码】
#include<stdio.h> #include<stdlib.h> int fa[105],cha[105]; int father(int x)//查询祖先,并维护与根节点的差 { int t; if(x!=fa[x]) { t=father(fa[x]); cha[x]+=cha[fa[x]];//维护与根节点的差 fa[x]=t; } return fa[x]; } int main() { int T,n,m,i,x,y,z,flag; scanf("%d",&T); for(;T>0;T--) { flag=0; scanf("%d%d",&n,&m); for(i=0;i<=n;i++)//初始化 { fa[i]=i; cha[i]=0; } for(i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); x--; if(father(x)!=father(y)) { cha[fa[y]]=cha[x]-cha[y]-z; fa[fa[y]]=fa[x];//将谁并入谁的集合都行 } else if(cha[x]-cha[y]!=z) flag=1; } if(flag==0) printf("true\n"); else printf("false\n"); } return 0; }
相关文章推荐
- PrefixHeader.pch 引入的头文件信息先后顺序很重要
- 3度带和6度带的区别
- Robot Motion 分类: POJ 2015-06-29 13:45 11人阅读 评论(0) 收藏
- C++关于二进制位操作小结
- Hive配置项的含义详解(5)
- JAVA 毫秒时间转字符显示
- xdebug安装和使用
- html 中文乱码
- ios构造函数
- Android 为LinearLayout增加分割线 divider
- android 录制音频的时候,调用麦克风出停止
- Android旋转本地图片并保存
- Google将不再支持Android Eclipse Tools
- ES6 Features系列:Template Strings & Tagged Template Strings
- 写给过去的自己-No.3-内存管理篇-KL25内存结构浅析
- ContentProvider+ContentObserver实例
- MSSQL - 逻辑主键、业务主键和复合主键
- LeetCode_67---Add Binary
- C#判断用户是否使用微信浏览器,并据此来显示真实内容或二维码
- 视频直播方面的知识ffmpeg