In this problem you will be given several descriptions of collections of nodes connected by directed edges. For each of these you are to determine if the collection satisfies the definition of a tree or 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 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.
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 Input
6 8 5 3 5 2 6 45 6 0 0
8 1 7 3 6 2 8 9 7 57 4 7 8 7 6 0 0
3 8 6 8 6 45 3 5 6 5 2 0 0
-1 -1
Sample Output
Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.
別看這道題的英文復(fù)雜,實(shí)際上題意真的簡單,題意如下:
就樣例來說,每兩個(gè)數(shù)字代表一條邊的兩端,也就是說這兩個(gè)數(shù)字代表一條邊,0 0代表一組數(shù)據(jù)的結(jié)束,-1 -1代表程序結(jié)束。
這一道題的目的就是為了判斷一下這些數(shù)字到底能不能組成一棵樹。
我們要知道,要組成一顆樹呢,首先,要沒有環(huán)(你見過一顆樹有環(huán)的嗎,反正我是沒有),其次,這棵樹只能有一個(gè)根節(jié)點(diǎn)(有兩個(gè)及以上的根節(jié)點(diǎn),這就不是樹了,是森林了),最后,一個(gè)點(diǎn)的入度最多為1(如果入度大于1了,那這些數(shù)構(gòu)成的不是有森林就是有環(huán)了),根節(jié)點(diǎn)入度為0。
還有,我們要注意一個(gè)坑點(diǎn),空樹也是一棵樹,也就是說直接給你一個(gè)0 0,這就是一個(gè)樹。
你們可能注意到我的寫法里面用了一下宏定義,其實(shí)適當(dāng)?shù)倪\(yùn)用宏定義不僅使得代碼的意思更好理解,還可以優(yōu)化我們的代碼。
這道題呢我是用并查集做的,不用并查集其實(shí)也能做。
代碼如下:
#include<cstdio>
#include<iostream>
#include<cstring>
#define cls(x) memset(x,0,sizeof(x))//代表清空一個(gè)數(shù)組
using namespace std;
const int MAXN=100010;
const int inf=1<<29;
bool flag=false;
int Min,Max;//這里的Min和Max代表得是點(diǎn)的大小范圍
int par[MAXN],in[MAXN];
bool exi[MAXN];//判斷一個(gè)點(diǎn)是否存在
int find(int x)
{
if(par[x]==x)return x;
return par[x]=find(par[x]);
}
void init()
{
for(int i=1;i<=MAXN;i++)
par[i]=i;
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y){
flag=true;//判斷是否有環(huán)
return ;
}
par[y]=x;
}
bool solve()
{
int cnt=0;
for(int i=Min;i<=Max;i++)
if(exi[i])
{
if(in[i]==0)cnt++;//判斷根結(jié)點(diǎn)
if(in[i]>1)return false;//判斷是否有入度大于1的點(diǎn)
}
if(cnt!=1)return false;
return true;
}
int main()
{
int a,b;
Min=inf,Max=-1;
int p=1;
init();
while(~scanf("%d%d",&a,&b))
{
if(a==-1&&b==-1)return 0;
if(a==0 && b==0)
{
if(Min==inf&&Max==-1){
printf("Case %d is a tree.\n",p++);
continue;
}
bool ans=solve();
if(ans && !flag)printf("Case %d is a tree.\n",p++);
else printf("Case %d is not a tree.\n",p++);
cls(in);
cls(par);
cls(exi);
Min=inf;
Max=-1;
init();
flag=false;
continue;
}
in[b]++;
if(Max<a)Max=a;//確定點(diǎn)范圍
if(Max<b)Max=b;
if(Min>a)Min=a;
if(Min>b)Min=b;
exi[a]=true;
exi[b]=true;
unite(a,b);
}
return 0;
}