描述
树是一种众所周知的数据结构,它既可以是空的(null),也可以是一个节点或多个节点的集合,这些节点通过有向边连接且满足以下属性。
有且仅有一个节点,我们称之为根节点,没有任何有向边指向该节点。
除了根节点外,每个节点都有且仅有一条指向它的边。
从根节点到每个其他节点都有一条唯一的有向边序列。
例如,参考下图,节点用圆圈表示,有向边用带箭头的线表示,前两个图形是树,最后一个图形不是树。
给定若干个由有向边连接的节点集合的描述,请确定它们是否满足树的定义。
输入描述:
输入包含多组测试数据。
每组数据占若干行,包含若干个对于有向边的描述,每个有向边的描述包含两个整数 aa 和 bb,表示这条有向边从节点 aa 指向节点 bb。
当出现数对 0 0
时,表示这组数据的输入结束。
当出现数对 -1 -1
时,表示全部输入结束。
具体可参考样例。
输出描述:
每个数据输出占一行,表示结果。
格式为 Case k is a tree.
或 Case k is not a tree.
,其中 kk 为组别编号,从 11 开始。
输入
6 8 5 3 5 2 6 4
5 6 0 0
8 1 7 3 6 2 8 9 7 5
7 4 7 8 7 6 0 0
3 8 6 8 6 4
5 3 5 6 5 2 0 0
-1 -1
输出
Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.
代码
#include<bits/stdc++.h>
using namespace std;
int fa[10010];
int main(){
function<int(int)> find;
find = [&](int a){ if(fa[a] != a) fa[a] = find(fa[a]);return fa[a];};
for(int i = 1; ; i++){
for(int i = 0; i < 10010; i++) fa[i] = i;
int a, b, ok = 1, m = 0;
bitset<10010> vis, ind;
while(scanf("%d%d",&a, &b) && a > 0){
if(ok){//
if(find(a) == find(b)) ok = 0;//有回路
else fa[fa[a]] = fa[b];
vis[a] = 1, vis[b] = 1;//记录点数
if(ind[b]) ok = 0; else ind[b] = 1;
m++;//边的数量
}
}
if(a == -1) break;
if(m + 1 != vis.count() && m) ok = 0;//边数 + 1 = 点数才是树
cout<<"Case "<<i<<" is "<<(ok ? "" : "not ")<<"a tree.\n";//输出
}
return 0;
}