[POJ 1308]Is It A Tree?[并查集][判断有向树]

题目链接: [POJ 1308]Is It A Tree?[并查集]

题意分析:

判断给出的有向图是不是一颗树。

解题思路:

嘛,首先得看看题目是怎么给树定义的。

一、树是n(n>=0)个结点的有限集

二、树没有环

三、是树,不是森林

四、有且仅有一个结点的入度为0

五、除树根外,结点入度为1

对于条件二,当某条边的左右两端点都属于一个集合时,就存在环了。

对于条件三,当某个结点的父亲结点和其它结点不同时,就存在森林了。

对于条件四,条件五,记录下入度判断就行了。

诶,不知道并查集是什么?这里推荐一篇超级棒的博文:点我

个人感受:

太久没写并查集了,合并函数都写错了TAT改编他们常说的话:“连合并函数都写错了,和咸鱼有什么区别!”XD。没注意到题目对树的定义,竟然空树也是树,这点要多注意。

PS:之前写的第一个版本只判断了条件1、2、3,POJ就给过了,3 8 6 8 0 0 这组数据第一版本说是一棵树,实际上这组数据结果应该是not。现在这一版本就没这个问题了。

最后吐槽一句:竟然不告诉我有多少结点!!!!

具体代码如下:

#include<iostream>
#include<cctype>
#include<cstdio>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<algorithm>
#include<map>
#include<iomanip>
#include<set>
#include<stack>
#include<queue>
#define ll long long
#define pr(x) cout << "#x = " << (x) << '\n';
using namespace std;

const int INF = 0x7f7f7f7f;
const int MAXN = 1e3 + 111;

int p[MAXN], e[MAXN]; //p:父亲结点 e:记录入度
bool exist[MAXN];  //记录下有哪些结点是存在在树上的

void init()
{
    for (int i = 0; i < MAXN; ++i)
    {
        exist[i] = 0;
        p[i] = i;
        e[i] = 0;
    }
}

int find(int x)
{
    return p[x] == x ? x : p[x] = find(p[x]);
}

bool unite(int a, int b)
{
    a = find(a), b = find(b);
    if (a == b) return 0; //形成环了
    p[a] = b;
    return 1;
}

int main()
{

    int kase = 0, a, b, root;
    while (~scanf("%d%d", &a, &b) && a != -1)
    {
        bool flag = 1;
        if (a == 0 && b == 0) goto ed; //空树
        init();
        root = a;
        ++e[b];
        exist[a] = exist[b] = 1;
        if (!unite(a, b)) flag = 0;
        while (scanf("%d%d", &a, &b) && (a || b))
        {
            exist[a] = exist[b] = 1;
            ++e[b];
            if (!unite(a, b)) flag = 0;
        }
        root = find(root);
        for (int i = 0; i < MAXN; ++i) //判森林 + 判是不是有向树
        {
            if (exist[i] && (find(i) != root || e[i] > 1))
            {
                flag = 0;
                break;
            }
        }
        ed:
        if (flag) printf("Case %d is a tree.\n", ++kase);
        else printf("Case %d is not a tree.\n", ++kase);
    }
    return 0;
}


你可能感兴趣的:(poj,并查集)