图论500题——POJ_P1308 Is_It_A _tree?
题目:
Is It A Tree?
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 33009 Accepted: 11196
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.
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 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
Sample Output
Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.
Source
North Central North America 1997
因为题目是英文的,所以这里大概的翻译一下:给出几条边,判断这能不能组成是不是一棵树。
在题目里有一点值得注意的是,题目是让你求这是不是一颗数,而不是森林,我就是因为没有考虑到这一点,所以WA了无数次。
这题可以直接用并查集来做这道题,不过要有一点小小的改动,就是把原来的father[i] = i,改成father[i] = -1,如果有用到在把他的father变成他自己,作用在于,题目的测试样例是可以跳跃节点的,也就是说,如果这个节点没有用到,那么就可以直接忽略这个节点,这也是此题的几个坑点,不过第二个坑点只要看样例输出就可以了。
然后再讲一讲此题的思路,先用一个并查集,来判断这条边的两个点是不是在一个联通块里,如果在联通两个点的时候,还没有合并就已经在一个集合就表示又环,不是树,最后在判断一下根节点有几个,如果不止一个表示这是一个森林,而不是树。
附上代码,代码在POJ上测试AC了,但在HDU上回WA,如果有哪位大佬发现了错误,还请大佬给本蒟蒻留言。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
int father[100001];
int get_father(int u)
{
while(father[u]!=u)u = father[u];
return u;
}
bool merge(int u,int v)
{
if(get_father(u)==get_father(v))return false;
father[get_father(u)] = get_father(v);return true;
}
void init()
{
for(int i = 0;i<100001;i++)father[i] = -1;
}
int main()
{
int u,v,num = 1;
while(1)
{
init();
std::cin>>u>>v;
if(u==0&&v==0){std::cout<<"Case "<<num++<<" is a tree."<<std::endl;continue;}
if(u<0||v<0)return 0;
bool flag = false;
while(!(u==0&&v==0))
{
if(father[u]==-1)father[u] = u;
if(father[v]==-1)father[v] = v;
if(merge(u,v)==false){std::cout<<"Case "<<num++<<" is not a tree."<<std::endl;flag = true;break;}
std::cin>>u>>v;
}
if(flag==false)
{
int count = 0;
for(int i = 0;i<100001;i++)
if(father[i]==i)count++;
if(count>1){std::cout<<"Case "<<num++<<" is not a tree."<<std::endl;flag = true;}
}
if(flag==false)std::cout<<"Case "<<num++<<" is a tree."<<std::endl;
else while(!(u==0&&v==0))std::cin>>u>>v;
}
return 0;
}
随时随刻,当你想要颓废的时候,想想之前为何而来,当你想要放弃的时候,想想之前你为何坐在这里