OJ_这是一颗树吗

题干

在这里插入图片描述
在这里插入图片描述

C++实现

树结构需要满足的三个条件

  • 不存在入度大于2的结点
  • 已连通的u,v,再加入一条新边就会成环
  • 边数 = 顶点数-1
#include <iostream>
#include <vector>
using namespace std;

//并查集的应用:判断图的连通性

int set[10001];
//i下标是集合数据编号,set[i]是i的父亲的编号
//若i是根,可令set[i] = i
void InitDisjointSet(int n) {
    for(int i = 0; i<n; ++i) {
        set[i] = i;
    }
}

int FindDisjointSet(int u) {
    if(u == set[u]) {
        return u;
    } else {
        set[u] = FindDisjointSet(set[u]);//压缩路径
        return set[u];
    }
}

int UnionDisjointSet(int u,int v) {
    int uRoot = FindDisjointSet(u);
    int vRoot = FindDisjointSet(v);
    //把v并到u上
    set[vRoot] = uRoot;
}

int main() {
    int u,v;
    InitDisjointSet(10001);
    int edgeCount = 0;
    int vertexCount = 0;
    //vertex[i] = 0说明i未出现过
    vector<int> vertex(10001);
    //inDegree[i]记录i的入度
    vector<int> inDegree(10001);
    //判断是否是棵树
    bool isOK = true;
    int caseIndex = 1;
    while(1) {
        scanf("%d%d",&u,&v);
        if(u == -1&&v==-1) {
            break;
        } else if(u == 0 && v==0) {
            //一个图的所有边已经记录完成了
            if(vertexCount!=edgeCount+1) {
                isOK =false;//有特例:空树
            }
            if(vertexCount == 0 &&edgeCount ==0) {
                isOK = true;
            }

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

            InitDisjointSet(10001);
            edgeCount = 0;
            vertexCount = 0;
            for(int i = 0; i<10001; ++i) {
                vertex[i] = 0;
                inDegree[i] = 0;
            }
            isOK = true;
            ++caseIndex;
        } else {
            //往当前图加入新边
            ++edgeCount;
            if(vertex[u] == 0) {
                vertex[u] = 1;
                ++vertexCount;
            }
            if(vertex[v] == 0) {
                vertex[v] = 1;
                ++vertexCount;
            }
            if(FindDisjointSet(u) == FindDisjointSet(v)) {
                //说明成环了
                isOK = false;
            } else {
                UnionDisjointSet(u,v);
            }
        }
        ++inDegree[v];
        if(inDegree[v]>=2) {
            isOK = false;
        }
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值