HDU-1325(Is it a tree?) 并查集

题目大意:给定多组数据,每组数据以0 0结尾,-1 -1结束输入。通过已知节点信息判断是不是一棵树

解题思路:看边和节点的关系,有无形成环;看是不是森林,即入度为0的根只有一个;除根节点外的每个节点入度不得超过1;

实现代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cassert>
#include<complex>//real().imag().
#include<cctype>
#include<algorithm>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<string>
#include<utility>
#include<iterator>
#define pii pair<int,int>
#define make_pair mp
using namespace std;
typedef long long ll;
const int N = 100005;//题目没给具体数据,瞎搞的
int root = 0;//根的数量
int indgree[N], f[N]; //入度
bool vis[N];//是否访问
int flag = 1;//决定结果
int cnt = 1;//case数量
int side = 0;//边的数量,用来判断空树
void init()//初始化
{
    root = 0;//根数为0
    side = 0;//边数为0
    flag = 1;//满足条件
    memset(f, -1, sizeof(f));//初始化根节点为-1
    memset(vis, false, sizeof(vis));//初始化为未访问
    memset(indgree, 0, sizeof(indgree));//初始化每个节点入度为0
}
int U_find(int x)//朴素查找,记得根节点默认是-1
{
    while (f[x] != -1)
    {
        x = f[x];
    }
    return x;
}
void U_merge(int x, int y)//把一对数的前者作为后者的根
{
    int xx = U_find(x);
    int yy = U_find(y);
    if (yy != xx)
    {
        f[yy] = xx;
    }
}
int main()
{
    int a, b;
    init();//开局初始化
    while (cin >> a >> b)//循环输入每一对数
    {
        side++;//因为插入一对,边数+1
        if (a == -1 && b == -1)//退出条件
            break;
        U_merge(a, b);//没退出的话,合并
        vis[a] = vis[b] = true;//标记访问过的节点
        indgree[b]++;//因为a是b的根,所以b的入度+1
        if (a == 0 && b == 0)//输入0 0时
        {
            if (side == 1)//如果只有一条边,说明是空树
            {
                cout << "Case " << cnt++ << " is a tree." << endl;
            }
            else
            {
                for (int i = 1; i <= N; ++i)//否则开始遍历所有节点
                {
                    if (vis[i])//遇到访问过的节点
                    {
                        if (indgree[i] >= 2)//入度>=2的话,说明不满足题意
                        {
                            flag = 0;//更易flag
                        }
                        if (indgree[i] == 0)//入度为0,说明该节点是树根
                        {
                            root++;
                        }
                    }
                }
                if (root == 1 && flag == 1)//满足条件同时根为1
                {
                    cout << "Case " << cnt++ << " is a tree." << endl;
                }
                else
                {
                    cout << "Case " << cnt++ << " is not a tree." << endl;
                }
            }
            init();//再次初始化迎接下一组测试数据
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cloudplankroader/p/10657469.html