ZOJ 1268 Is It A Tree?

题目连接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1268

测试例

一定在思考的时候考虑问题考虑得全面一些,注意几种特殊情况:
0 0
 空树是一棵树(没考虑到)
1 1 0 0
 不是树 不能自己指向自己(没考虑到)
1 2 1 2 0 0
 不是树 重复不行
1 2 2 3 4 5 0 0
不是树 森林不算是树(主要是注意自己)
1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 1 0 0
 注意 一个节点在指向自己的父亲或祖先 都是错误的  9-->1 
1 2 2 1 0 0
 也是错误的

/*
	1. 判断入读大于2, 说明有环不行
	2. 判断入读为0的个数只能为1, 为0或大于1都不行, 有头节点且只能有一个
	3. 空树也是树
  */
#include "iostream"
#include "cstring"
using namespace std;
int nodes[1024],ideg[1024];				//nodes存储节点, ideg存储其相应的度
int main(){
	int node1,node2, count = 0; 
	int num = 1;						//测试例
	int isT = 1;						//是不是树, 先置为1	
	memset(nodes, 0, sizeof(nodes));
	memset(ideg, -1, sizeof(ideg));
	while(cin>> node1 >> node2 && ( node1 != -1 ) && ( node2 != -1 )){
		if(node1 == node2 && node1 == 0){	//如果输入的两个数都是0, 进入判断是不是树
				
			int zcount=0;					//存储度为0的节点数
			int i = 0;
			for(i = 1; i <= count;i++){
				if(ideg[i] == 0)
					zcount++;

				if(ideg[i] > 1)
					isT = 0;
			
				
			}

			if(zcount != 1)
				isT = 0;

			if(isT || count == 0)			// count == 0即空树也是树
				cout<<"Case "<<num++<<" is a tree."<<endl;
			else 
				cout<<"Case "<<num++<<" is not a tree."<<endl;
			//恢复数据
			count = 0;
			isT = 1;
			memset(nodes, 0, sizeof(nodes));
			memset(ideg, -1, sizeof(ideg));

		} else {
			if(node1 == node2)				//如果两个节点相等, 不是树
				isT = 0;
		
			int i = 0,flag1 = 0,flage2 = 0;
			for(i = 1 ;i <= count; i++){  
				if(node1 == nodes[i])		//如果数组里有node1, 则不管, 因为它是父节点
					flag1 = 1;	
				if(node2 == nodes[i]){		//如果弄得有node2, 则他的入度加1
					flage2 = 1;
					ideg[i]++;		
				}
			}

			if(!flag1){						//如果没有node1, 则新增一个位置存储node1, 并将其入度置为0
				nodes[++count] = node1;
				ideg[count] = 0;
			}
			
			if(flage2 == 0){				//如果没有node2, 则新增一个位置存储node2, 并将其入度置为1
				nodes[++count] = node2;
				ideg[count] = 1;
			} 
		}
	}
	return 0;
}

    2012-12-07

并查集

   

#include<iostream>
#include <cstring>
using namespace std;

int pre[1024], flage, rank[1024];
int find(int x){	//num表示找到头所用的步数
	if(pre[x] == x || pre[x] == -1){
		return x;
	}
	return pre[x] = find(pre[x]);
}
void join(int x, int y){
	
	int num_x = 0, num_y = 0;
	int temp_x = find(x);
	int temp_y = find(y);
	//当前入度为1,则不能再有指向它的了
	if(rank[y] >= 1)
		flage = false;
	//两个父节点相同就会有环, 1 1  0 0类似这种情况也可以排除
	else if(temp_x == temp_y){	
		flage = false;
	}
	else{
		pre[temp_x] = temp_y;
		pre[temp_y] = -1;	//temp_y为头结点
		rank[temp_y]++;		//temp_y的入度加1 
	}
}

int main(){
	//初始化数据
	int i,iCase = 0, x, y, count = 0;
	for(i = 0; i < 1024; i++)
		pre[i] = i;
	flage = true;
	memset(rank, 0, sizeof(rank));

	while(cin>>x>>y){
		if(x == -1 && y == -1)
			return 0;
		if(x == 0 && y == 0){
			for(i = 0; i < 1024; i++){
				if(pre[i] == -1)	//头结点标志为父节点-1
					count++;
				if(count > 1){		//头结点个数大于1
					flage = false;
					break;
				}
			}
			//输出结果
			if(flage == false)
				cout<<"Case "<<++iCase<<" is not a tree."<<endl;
			else
				cout<<"Case "<<++iCase<<" is a tree."<<endl;
			//恢复数据
			flage = true;
			count = 0;
			for(i = 0; i < 1024; i++)
				pre[i] = i;
			memset(rank, 0, sizeof(rank));
		}
		else if(flage)
			join(x, y);
	}
    return 0;
}

你可能感兴趣的:(ACM)