您的位置:首页 > 其它

HDU-1325-Is It A Tree?

2016-10-25 01:59 381 查看
ACM模版

描述



题解

这道题方法很多,比较好的方法是直接根据树的性质来判断,先判断是否有环,可以通过边数来判断,n个结点最多有n-1条边,不然一定会有环,接着判断根的个数,也就是入度为0的个数,必须为1,最后判断其他根节点入度是否都为1,否则说明不是树!

当然,判断环的部分也可以用并查集,但是这个并查集需要注意些剪枝优化,不然会TLE的,我一开始直接拿着小希的迷宫的代码改了一行提交,TLE了两次……怪我太天真了。

代码

#include <stdio.h>

const int MAXN = 100010;

typedef struct
{
int num, root, conn;    //  数据、根、入度
} Node;

int NodeNum;
Node node[MAXN];

void init()
{
NodeNum = 0;
for (int i = 0; i < MAXN; i++)
{
node[i].conn = 0;   //  入度初始化为0
node[i].root = i;   //  根记录为自身
node[i].num = 0;    //  标记数字是否被使用过,0:没有被使用过,1:使用过了
}
}

int find_root(int a)
{
if (node[a].root != a)
{
return node[a].root = find_root(node[a].root);
}
return node[a].root;
}

void union_set(int a, int b)
{
a = find_root(a);
b = find_root(b);
if (a == b)         //  同一个根,说明是在同一个树下
{
return ;
}
node[b].root = a;   //  把b的根赋为a的根,此时a已经是根,num==root
}

int main()
{
int n, m;
int i = 1;
bool flag = true;   //  true:是个树,false:不是树
init();
while (scanf("%d%d", &n, &m) != EOF && n >= 0 && m >= 0)
{
if (n > NodeNum)
{
NodeNum = n;
}
if (m > NodeNum)
{
NodeNum = m;
}
if (!flag && n != 0 && n != 0)
{
continue;   //  已经确定不是树了,就继续循环
}

if (n == 0 && m == 0)
{
int root_num = 0;
for (int j = 1; j <= NodeNum;j++)
{
//  判断是否为森林,root_num用来记录根的数目
if (node[j].num && find_root(j) == j)
{
root_num++;
}
if (node[j].conn > 1)   //  如果出现某个节点的入度超过1,不是树
{
flag = false;
break;
}
}
if (root_num > 1)   //  连通分支大于1,是森林不是树
{
flag = false;
}

if (flag)
{
printf("Case %d is a tree.\n", i++);
}
else
{
printf("Case %d is not a tree.\n",i++);
}

flag = true;
init();
continue;
}

if (m != n && find_root(n) == find_root(m))
{
flag = false;
}
else
{
//  将m,n,记录为节点
node[m].num = 1;
node
.num = 1;
node[m].conn++;     //  入度增加一
union_set(n, m);
}
}
return 0;
}


参考

HDU 1272 小希的迷宫
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并查集