poj1308 Is It A Tree?(并查集)详解

poj1308   http://poj.org/problem?id=1308

题目大意:输入若干组测试数据,输入 (-1 -1) 时输入结束。每组测试数据以输入(0 0)为结束标志。然后根据所给的所有(父亲, 孩子)数据对判断 是否能构成一棵树。

分析:  都以了解树只有一个根节点,那么我们就判断是不是有多个树;又知道每个节点只有一个父亲节点,那么我们就判断他是不是构成环,成环则不是树。

注意: ①可以是空树; ②所给的节点构成森林(多个树)是不可以的,必须只能构成一棵树。

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;

int out, flag, x, y, num, pre[10010];
int find(int a)//查找根节点
{
    int r, i, j;
    r = a; i = a;
    while(pre[r] != r)
        r = pre[r];
    while(pre[i] != r)
    {
        j = pre[i];
        pre[i] = r;
        i = j;
    }
    return r;
}
int main()
{
    num = 0; out = 1;
    while(out)
    {
        //先对所有节点的根节点进行初始化
        for(int i = 1; i <= 10000; i++)
            pre[i] = i;

        flag = 1;
        while(scanf("%d%d", &x, &y))
        {
            if(x == 0 && y == 0)
                break;
            else if(x == -1 && y == -1)
            {
                out = 0;
                break;
            }
            int fx = find(x);
            int fy = find(y);
            //此处我们判断是否构成环
            //如果x和y的根节点相同,那么他们已经是属于同一棵树
            //若x又是y的父亲节点,那么将构成环
            if(fx == fy)
                flag = 0;
            //如果x和y根节点不同,即不属于同一棵树, 那么将其合并成一棵树
            else if(fx != fy)
                pre[fy] = fx;
        }
        int k = 0;
        //此处我们判断是不是森林,对所有节点(不包括没涉及的点)的根节点
        //进行统计,若不都一样那么说明存在多个跟, 有多颗树, 否则是一棵树。
        for(int i = 1; i <= 10000; i++)
        {
            int ans = find(i);
            if(ans != i && k == 0)
                k = ans;
            else if(k != 0 && ans != i)
            {
                if(ans != k)
                    flag = 0;
            }
        }
        if(out == 1 && flag == 0)
            printf("Case %d is not a tree.\n", ++num);
        else if(out == 1 && flag == 1)
            printf("Case %d is a tree.\n", ++num);
    }
    return 0;
}

杭电的1272 和这个题差不多  稍微改改就可以了。

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;

int out, flag, x, y, pre[100010];
int find(int a)
{
    int r, i, j;
    r = a; i = a;
    while(pre[r] != r)
        r = pre[r];
    while(pre[i] != r)
    {
        j = pre[i];
        pre[i] = r;
        i = j;
    }
    return r;
}
int main()
{
    out = 1;
    while(out)
    {
        for(int i = 1; i <= 100000; i++)
        {
            pre[i] = i;
        }
        flag = 1;
        while(scanf("%d%d", &x, &y))
        {
            if(x == 0 && y == 0)
                break;
            else if(x == -1 && y == -1)
            {
                out = 0;
                break;
            }
            int fx = find(x);
            int fy = find(y);
            if(fx != fy)
            {
                pre[fx] = fy;
            }
            else if(fx == fy)
            {
                flag = 0;
            }
        }
        int k = 0;
        for(int i = 1; i <= 100000; i++)
        {
            int ans = find(i);
            if(ans != i && k == 0)
                k = ans;
            else if(k != 0 && ans != i)
            {
                if(ans != k)
                    flag = 0;
            }
        }
        if(out == 1 && flag == 0)
            printf("No\n");
        else if(out == 1 && flag == 1)
            printf("Yes\n");
    }
    return 0;
}

时间: 2024-10-23 22:34:06

poj1308 Is It A Tree?(并查集)详解的相关文章

并查集详解(转)

并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了.以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定.不分享出来真是对不起party了.(party:我靠,关我嘛事啊?我跟你很熟么?) 来看一个实例,杭电1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块.像畅通工程这题,问还需要修

并查集详解(转自一个很有才的大神)膜拜

并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了.以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定.不分享出来真是对不起party了.(party:我靠,关我嘛事啊?我跟你很熟么?) 来看一个实例,杭电1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块.像畅通工程这题,问还需要修

并查集详解 (转)

http://blog.csdn.net/dellaserss/article/details/7724401 我从CSDN转的文章,原文作者我也不懂是谁,文章写得真的是诙谐幽默,使得内容更容易理解了. 来看一个实例,杭电OJ 1232畅通工程 Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可).问最少还需要建

【转】并查集详解

来看一个实例,杭电1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块.像畅通工程这题,问还需要修几条路,实质就是求有几个连通分支.如果是1个连通分支,说明整幅图上的点都连起来了,不用再修路了:如果是2个连通分支,则只要再修1条路,从两个分支中各选一个点,把它们连起来,那么所有的点都是连起来的了:如

读书笔记 之 数据结构(并查集详解)(POJ1703)

<ACM/ICPC算法训练教程>读书笔记-这一次补上并查集的部分.将对并查集的思想进行详细阐述,并附上本人AC掉POJ1703的Code. 在一些有N个元素的集合应用问题中,通常会将每个元素构成单元素集合,然后按照一定顺序将同属一组的集合合并,期间要反复查找每一个元素在哪个集合中.这类问题往往看似简单,但是数据量很大,因此容易造成TLE或MLE,也就是空间度和时间度极其复杂.因此在这里,我们引入一种抽象的特殊数据结构——并查集. 并查集:类似一个族谱,每个结点均有一个father[x]来表示x

并查集详解---(转)

并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了.以前我无法解决的一类问题竟然可以用如此简单高效的方法搞定.不分享出来真是对不起party了.(party:我靠,关我嘛事啊?我跟你很熟么?) 来看一个实例,杭电1232畅通工程 首 先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个 点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块.像畅通工程这题,问还需

[转]并查集详解

来看一个实例,杭电1232畅通工程 首 先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个 点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块.像畅通工程这题,问还需要修几条路,实质就是求有几个连 通分支.如果是1个连通分支,说明整幅图上的点都连起来了,不用再修路了:如果是2个连通分支,则只要再修1条路,从两个分支中各选一个点,把它们连起 来,那么所有的点都是连起来

并查集详解及模板

概念: p { margin-bottom: 0.25cm; direction: ltr; color: #000000; line-height: 120%; text-align: justify; orphans: 0; widows: 0 } p.western { font-family: "Calibri", "Lucida Sans Unicode", sans-serif; font-size: 10pt } p.cjk { font-family

并查集详解

使用并查集查找时,如果查找次数很多,那么使用朴素版的查找方式肯定要超时.比如,有一百万个元素,每次都从第一百万个开始找,这样一次运算就是10^6,如果程序要求查找个一千万次,这样下来就是10^13,肯定要出问题的. 这是朴素查找的代码,适合数据量不大的 int findx(int x) { int r=x; while(parent[r] !=r) r=parent[r]; return r; } 下面是采用路径压缩的方法查找元素: int find(int x) //查找x元素所在的集合,回溯

hdu1325is it a tree?&amp;&amp;poj1308 is it a tree?(并查集)

题目链接: huangjing||huangjing 建议做hdu上的这个题,因为poj上面的数据很弱,就是因为只做了poj上面的导致我在一次比赛中一直wa到比赛结束,因为比赛的那次挂的是hdu上的题... 题意: 判断由给出的数据得到的是否是一棵树... 思路: 这个题有几个要注意的地方. [1]首先一棵树只能有一个入度为0的点即根节点..所以根节点唯一.. [2]除根节点外其他点的入度均为1. 题目: Language: Default Is It A Tree? Time Limit: 1