HDU 1325 Is It A Tree?(并查集)
2015-11-07 20:34
441 查看
题目大意:
给你两个节点,前者指向后者(可以认为前者是后者的父节点),然后让你判断是否是一棵树。
解题思路:
先说说这道题和小希的迷宫(HDU1272)那道题的区别,前者给出的两个点是有方向的,而后者是没有的,这就是唯一的区别。再者这道题其实就是让你判断所有的点最后所形成的图是否是一棵树。做这道题时错误了很多遍,细想之,主要是开始思路不好,很容易乱,理清思路让代码变得清晰起来就好了。判断一个图是否为一棵树。有三个重要条件(比小希的迷宫多了一个条件):
1:已经在一个集合里面的两个数不能再同时出现了(无环图)。
2:根节点只有一个(是树不是森林)。
3:除了根节点之外所有的节点的入度为一。
上面三个条件都满足了就是一颗树了,对于第一个条件,即判断是否新给的两个数的根节点是否相同。第二个条件最后统计一下根节点的数量是否小于2,(不是等于一,因为空树也是树,根节点为0~~~),第三个条件,可以观察观察数据,入度是指被指向的那个点,对于每次给定的两个数,后面那个数字出现的次数即是这个点的入度。所以可以用一个数组,利用下标代表这个点,利用值代表出现的次数。最后统计下看是否有出现次数大于一的。
给你两个节点,前者指向后者(可以认为前者是后者的父节点),然后让你判断是否是一棵树。
解题思路:
先说说这道题和小希的迷宫(HDU1272)那道题的区别,前者给出的两个点是有方向的,而后者是没有的,这就是唯一的区别。再者这道题其实就是让你判断所有的点最后所形成的图是否是一棵树。做这道题时错误了很多遍,细想之,主要是开始思路不好,很容易乱,理清思路让代码变得清晰起来就好了。判断一个图是否为一棵树。有三个重要条件(比小希的迷宫多了一个条件):
1:已经在一个集合里面的两个数不能再同时出现了(无环图)。
2:根节点只有一个(是树不是森林)。
3:除了根节点之外所有的节点的入度为一。
上面三个条件都满足了就是一颗树了,对于第一个条件,即判断是否新给的两个数的根节点是否相同。第二个条件最后统计一下根节点的数量是否小于2,(不是等于一,因为空树也是树,根节点为0~~~),第三个条件,可以观察观察数据,入度是指被指向的那个点,对于每次给定的两个数,后面那个数字出现的次数即是这个点的入度。所以可以用一个数组,利用下标代表这个点,利用值代表出现的次数。最后统计下看是否有出现次数大于一的。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <cctype> #include <algorithm> using namespace std; const int MAXN = 1e5 + 3; int pre[MAXN]; //储存父节点 bool bol[MAXN]; //这个点是否出现过 int flag1 = 1; //代表入度是否满足是一个树 int flag2 = 1; //代表是否成环。 int cnt[MAXN]; //记录出现的点的入度 int Find(int x) { int r = x; while(pre[r] != r) { r = pre[r]; } int i = x,j; while(pre[i] != r) { j = i; i = pre[i]; pre[j] = r; } return r; } void Mix(int a,int b) { int x = Find(a); int y = Find(b); if(x > y) { pre[x] = y; } if(x < y) { pre[y] = x; } } int Search() { int cnt = 0; for(int i = 1; i <= MAXN; i++) { if(bol[i]) if(pre[i] == i) cnt++; } return cnt; } int main() { int M,N; flag1 = 1; //一大堆初始化0.0 flag2 = 1; for(int i = 1; i <= MAXN; i++) { pre[i] = i; bol[i] = false; } memset(cnt,0,sizeof(cnt)); int kas = 1; while(~scanf("%d%d",&M,&N)&&(M != -1 || N != -1)) { bol[M] = true; bol = true; cnt ++; if(M != 0 && N != 0) { int m = Find(M); int n = Find(N); if(m == n) flag2 = 0; //出现了环 Mix(M,N); } else { int single = Search(); //根节点的个数 for(int i = 1; i <= MAXN;i++) { if(cnt[i] > 1) flag1 = 0; //有入度大于一的出现 } if(single < 2 && flag1 && flag2) printf("Case %d is a tree.\n",kas++); //三个条件都满足 else printf("Case %d is not a tree.\n",kas++); flag1 = 1; flag2 = 1; for(int i = 1; i <= MAXN; i++) { pre[i] = i; bol[i] = false; } memset(cnt,0,sizeof(cnt)); } } return 0; }
相关文章推荐
- 活动的四种启动模式
- 传递给Appium服务器以开启相应安卓Automation会话的Capabilities的几点说明【转】
- (转)java判断string变量是否是数字的六种方法小结
- Android组件之间的通信
- UML 总结
- 互联网+O2O 的商业模式
- java连接mongod抛java.net.SocketTimeoutException: connect timed out异常(2015-11-07 20:29:58)
- Introduction-to-React-JS
- 多操作符的语义判断(如 int& *a和int* &a)
- 自己做灭火机器人(一)——硬件准备与车体搭建
- 不借用临时变量交换两个整数的值
- Spark 入门之一:CentOS 6.5 下Spark 1.4 的安装以及配置
- 网站如何记录访客的个人信息?
- lesson18 Aliasing
- 关于文件上传的学习心得
- 最优化方法—一维搜索
- 应用层(一)
- Java多线程的实现方法
- [ecshop 调试 ]ecshop中的 debug_mode 是在哪里定义的 查看sql日志 输出错误 显示debug
- c++ 学习的资源汇总