并查集,不复杂,但是我一直不甚理解,用得不好。这几天对并查集做了些针对性训练。算了有了一个初步的了解。这里稍微进行一下整理。
poj 1308
给定一个图的一些边 判断这个图是不是树。
利用并查集,把联结的点放在同一集合,利用findset判断是否存在环。
需要注意的是,森林不是树,所以讲边扫描完毕后,需要遍历每个点,看看有几个点是入度为零的,如果只有一个点是入度为零,那么就是树;不然就是森林了。
/* 1: 0 0 空树是一棵树
2: 1 1 0 0 不是树 不能自己指向自己
3: 1 2 1 2 0 0 不是树....自己开始一直在这么WA 好郁闷 重复都不行呀~~5555
4: 1 2 2 3 4 5 不是树 森林不算是树(主要是注意自己)
5: 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 1 注意 一个节点在指向自己的父亲或祖先 都是错误的 即 9-->1 错
6: 1 2 2 1 0 0 也是错误的
*/
#include <iostream>
#include <cstdio>
#include <cstring>
namespace std;
int maxn = 1010;
int father[maxn];
bool visit[maxn],od[maxn];
int u)
16: {
return u;
return getfather(father[u]);
19: }
int v)
21: {
if(getfather(u) == getfather(v))
return true;
return false;
25: }
int v)
27: {
int uu = getfather(u);
int vv = getfather(v);
30: father[vv] = uu;
31: }
int main()
33: {
int x,y,cas=0;
bool flag;
while(++cas)
38: {
39: flag = true;
int i=1;i<=maxn-10;++i)
41: father[i] = i;
sizeof(visit));
sizeof(od));
,&x,&y) && x>0 && y>0)
45: {
if(x==y)
47: {
48: flag = false;
,&x,&y) && x!=0);
break;
51: }
if(findset(x,y))
53: {
54: flag = false;
,&x,&y) && x!=0);
break;
57: }
else
59: {
60: united(x,y);
61: visit[y] = true;
62: visit[x] = true;
63: od[y] = true;
64: }
65: }
break;
int cnt = 0;
int i=1;i<=maxn-10;++i)
69: {
if(visit[i] == true && od[i] == false)
71: ++cnt;
if(cnt>1)
73: {
74: flag = false;
break;
76: }
77: }
,cas);
,cas);
80: }
81: }