我的涂鸦圣地 » 日志 » 写了好几道判断树的题目了,都是用极光的并查集来做的,归纳一下!
写了好几道判断树的题目了,都是用极光的并查集来做的,归纳一下!
zl 发表于 2006-05-09 22:27:00
具体题目
//hdoj小系的迷宫
//zoj Is it a tree
//zoj message system
题目虽然有点不同,但都用到了相同并查集, 以及树的定义来判断
用并查集, 就是每次都新加一个节点,然后把它归到已有的节点集合中去, 假如每次都能合并成功(前提是读入这条边的两个节点还未在已有集合中连通,假如连通,则可以判断存在环,因为树中的点只能被连通一次, 即入度为1.)
这样就可以判断他是个无环图, 然后在按照树的定义来判断它的连通就ok了
同样,也可以用宽搜来达到证明图连通的目的,但是同样要借助树的定义来判断它是否存在环.
树的定义: node = edge + 1
//并查集(rights reserved by JGShining)
/*
适用范围:集合中元素范围是[1..MAXN]
*/
#include<stdio.h>
#include<memory.h>
#define MAXN 100000
int p[MAXN + 1], r[MAXN + 1];
// 初始化数据结构
void init_set()
{
memset(p, 0, sizeof(p));
}
// 生成一个新的集合,其中只含有一个元素e
void make_set(int e)
{
p[e] = e;
r[e] = 0;
}
// 返回0表示并查森林中找不到该元素
int find_set(int key)
{
if(key != p[key]) p[key] = find_set(p[key]);
return p[key];
}
// 合并两个集合s1和s2,以rank大的作为根
void union_set(int s1, int s2)
{
int p1, p2;
if(s1 == s2) return;
p1 = find_set(s1);
p2 = find_set(s2);
if(p1 != p2)
{
if(r[p1] > r[p2]) p[p2] = p1;
else if(r[p2] > r[p1]) p[p1] = p2;
else
{
r[p1]++;
p[p2] = p1;
}
}
}
注意,在实现有向树的过程中,合并集合的方法必须是把弧顶节点合并到弧尾节点,就是说,把子节点合并到根节点
相关日志:
收藏:
QQ书签
del.icio.us
