图论——并查集(三):判断是否为树

Sample

Description

A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties.
There is exactly one node, called the root, to which no directed edges point.没有任何边指向根节点
Every node except the root has exactly one edge pointing to it. 只有一个指向它的边
There is a unique sequence独特的有向边序列 of directed edges from the root to each node. For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are trees, but the last is not.
在这里插入图片描述

Input

The input will consist of a sequence of descriptions (test cases) followed by a pair of negative integers. Each test case will consist of a sequence of edge descriptions followed by a pair of zeroes每个testcase以0结束 Each edge description will consist of a pair of integers; the first integer identifies the node from which the edge begins, and the second integer identifies the node to which the edge is directed指向. Node numbers will always be greater than zero and less than 10000.结点数小于10000

Output

For each test case display the line “Case k is a tree.” or the line “Case k is not a tree.”, where k corresponds to the test case number (they are sequentially numbered 按顺序编号 starting with 1).

Sample
在这里插入图片描述

  • 解决方案:
    有向边连接的结点集合

  • 需要判断:

    1. 是否属于同一个集合(只有一个根节点
    2. 各个点是否符合树的定义(判断入度是否符合要求:根节点入度为0,其余点入度为1
  • 和本题树相关的数据结构:

    1. 维护一个inDegree[MAXN]数组存结点入度,初始化入度为0
    2. 维护一个visit[MAXN]数组标记是否为树中结点,初始化为true
  • 注意三个点:

    1. 空集也是树 连通分量=0&&根=0!!!一定注意是&&不是||,我敲代码总是在这种愚蠢的地方出现问题
    2. 输入数据时,指向的结点入度+1,来记录入度数据
    3. 利用一个visit数组来记录是否为树中结点,因为我们使用了数组,但是并不输入树中结点的个数~而是以0 0结束testcase, 以-1 -1结束输入

Source

北京大学复试上机题
Solution

#include <iostream>
#include <cstdio>

using namespace std;

const int MAXN = 10000;

int father[MAXN];
int height[MAXN];
int inDegree[MAXN];
bool visit[MAXN];

void Initial(){
    
    
    for(int i = 0; i < MAXN; ++i){
    
    
        father[i] = i;
        height[i] = 0;
        inDegree[i] = 0;
        visit[i] = false;
    }
}

// find root
int Find(int x){
    
    
    if(x != father[x]){
    
    
        father[x] = Find(father[x]);
    }
    return father[x];
}

void Union(int x, int y){
    
    
    x = Find(x);
    y = Find(y);
    if(x != y){
    
    
        if(height[x] < height[y]){
    
    
            father[x] = y;
        }else if(height[y] < height[x]){
    
    
            father[y] = x;
        }else{
    
    
            father[y] = x;
            height[x]++;
        }
    }
    return ;
}

bool IsTree(){
    
    
    bool flag = true;
    int conponent = 0;
    int root = 0;
    for(int i = 0; i < MAXN; ++i){
    
    
        if(!visit[i]){
    
    
            continue; // 遍历过了 pass
        }

        // 连通分量数目
        if(father[i] == i){
    
    
            conponent++;
        }
        
        // 入度限制
        if(inDegree[i] == 0){
    
    
            root++; // count 根节点
        }else if(inDegree[i] > 1){
    
    
            flag = false; // 入度大于1 不是树
        }
    }

    if(conponent != 1 || root != 1){
    
     // 不符合树定义
        flag = false;
    }
    if(conponent == 0 && root == 0){
    
      // 妈的 根为0 元素为0才是空树
    // 空集也是树!!!!
        flag = true;
    }
    return flag;
}

int main(){
    
    
    int x, y;
    int caseNumber = 0;
    Initial();
    while(scanf("%d %d", &x, &y) != EOF){
    
    
        if(x == -1 && y == -1){
    
    
            break;
        }

        if(x == 0 && y == 0){
    
    
            if(IsTree()){
    
    
                printf("Case %d is a tree.\n", ++caseNumber);
            }else{
    
    
                printf("Case %d is not a tree.\n", ++caseNumber); // CASE NUM 忘了前自增了 导致输出错误
            }
            Initial();
        }else{
    
    
            Union(x, y);
            inDegree[y]++;
            visit[x] = true;
            visit[y] = true;
        }
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_44145782/article/details/116485671