#判断图是否是树#并查集#北京大学复试
https://www.acwing.com/problem/content/3412/
思路:本题需要判断一个图是否为树,这需要我们判断三个要素:
1.一个树的边数应该比节点数少1
2.一个树的节点入度应该小于等于2,且只有一个入度为0的节点即根节点
3.从根节点到任意节点有且仅有一条唯一路线
1我们使用两个计数变量edgecount和vertexcount解决,2我们用入度数组和访问数组解决,3我们用并查集解决,并维护一个布尔型变量记录当前是否判断可以成树
注意点:1.每次完成后需要将数组变量进行初始化防止影响下一步2.将布尔型变量修改后不需要return而是应该继续循环直到所有数据都处理完成
/*树是一种众所周知的数据结构,它既可以是空的(null),也可以是一个节点或多个节点的集合,这些节点通过有向边连接且满足以下属性。
有且仅有一个节点,我们称之为根节点,没有任何有向边指向该节点。
除了根节点外,每个节点都有且仅有一条指向它的边。
从根节点到每个其他节点都有一条唯一的有向边序列。
给定若干个由有向边连接的节点集合的描述,请确定它们是否满足树的定义。
输入格式
输入包含多组测试数据。每组数据占若干行,包含若干个对于有向边的描述,每个有向边的描述包含两个整数 a和 b,
表示这条有向边从节点 a指向节点 b。当出现数对 0 0 时,表示这组数据的输入结束。当出现数对 -1 -1 时,表示全部输入结束。
输出格式:每个数据输出占一行,表示结果。格式为 Case k is a tree. 或 Case k is not a tree.,其中 k为组别编号,从 1开始。
数据范围0<a,b<10000,每个输入最多包含 100 组数据。
输入样例
6 8 5 3 5 2 6 4
5 6 0 0*/
#include <bits/stdc++.h>
using namespace std;
int father[10001];
void initialize(int n) {
for (int i = 0; i < n; i++) {
father[i] = i;
}
}
int findele(int u) {
if (u == father[u]) { //节点的下标与数组值相等,即为找到了根节点
return u;
} else {
father[u]=findele(father[u]);//继续向上找
return father[u];
}
}
void Unionele(int i, int j) {
int uroot;
uroot = findele(i);
int vroot;
vroot = findele(j);
father[vroot] = uroot;
}
int main() {
int u,v;
initialize(10001);
int edgeCount = 0;//边数
int vertexCount = 0;//顶点数
vector<int> vertex(10001); // vertex[i] -> 0 说明 i 未出现过
vector<int> inDegree(10001); // inDegree[i] 记录i的入度
bool isOK = true;
int caseIdx = 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 == true){
printf("Case %d is a tree.\n",caseIdx);
}
else{
printf("Case %d is not a tree.\n",caseIdx);
}
initialize(10001);
edgeCount=0;
vertexCount = 0;
for (int i = 0; i < 10001; ++i) {
vertex[i] = 0;
inDegree[i] = 0;
}
isOK = true;
++caseIdx;
}
else{//继续输入
edgeCount++;
if(vertex[u] == 0){
vertex[u] = 1;
++vertexCount;
}
if(vertex[v]==0){
vertex[v] = 1;
++vertexCount;
}
if(findele(v)== findele(u)){
isOK = false;
}
else{
Unionele(u,v);
}
++inDegree[v];
if(inDegree[v]>=2){
isOK = false;
}
}
}
return 0;
}
