POJ 1308 Is It A Tree?

题目大意:

        树的定义为:

        1. 由0个、1个或多个结点和有向边组成;

        2. 除了根结点入度为0,其余结点入度为1;

        3. 每个点从根结点到它都可达;

        现有多个测例,每个测例都给出若干条边的描述"x y",x、y为结点编号,从1开始,表示y为x的子结点,程序以两个负数结束,每个测例以"0 0"结束,要求对于每个测例判断输入的是否为一棵树。

        注意:结点数在15个左右,树中所有结点的编号并不一定能组成一段连续的数!!

题目链接

注释代码:

/*                 
 * Problem ID : POJ 1308 Is It A Tree?    
 * Author     : Lirx.t.Una                 
 * Language   : C++            
 * Run Time   : 0 ms                 
 * Run Memory : 152 KB                 
*/

#include <iostream>
#include <cstring>
#include <cstdio>

//最大结点数
#define	MAXN		15

using namespace std;

char	fath[MAXN];
bool	vist[MAXN];//标记每个结点是否被访问过

int
find(int x) {
	
	if ( x == fath[x] ) return x;
	
	return fath[x] = find( fath[x] );
}

int
main() {
	
	int		t;//测例数
	int		x, y;//接受临时输入的结点编号
	
	int		i;//计数变量
	
	int		node;//结点总数
	int		edge;//边的总数
	
	bool	isTree;//标志当前是否是一棵树或森林
	
	t = 0;
	while ( scanf("%d%d", &x, &y), x >= 0 ) {//输入为负整个程序结束
		//一个测例输入的开始
		
		//输入为0表示一个测例结束
		if ( !x ) {//没有任何结点,表示一棵空树
			//因此也是树
			
			printf("Case %d is a tree.\n", ++t);
			continue;
		}
		
		//树非空则初始化
		memset(vist, false, sizeof(vist));//每个结点都未访问过
		for ( i = 0; i < MAXN; i++ ) fath[i] = i;
		
		node = 0;
		edge = 0;
		
		isTree = true;
		
		do {
			
			if ( !isTree ) continue;//如果之前已经判断出不是树了,则后面的检查都可省略
			
			if ( x == y ) {//如果结点有自反性那肯定也不是树
				
				isTree = false;
				continue;
			}
			
			//输入x y时是表示y是x的子结点的!!

			//如果find(y) == y就表示y还未和任何结点合并过
			//但是如果find(y) != y就表示y已经和其它结点合并过了
			//由于合并操作是将子结点接在集合(树)的根结点上的
			//因此find(y) != y表示y之前已经属于某棵树的子结点了,因此其入度已经为1了
			//这里y又是x的子结点,因此x的入度就大于1了,因此如果find(y) != y则输入一定不是一棵树
			if ( find(y) == y ) fath[y] = find(x);//将y并入,并将y接在树的根结点处
			//!!注意:并查集根结点也是树的根结点
			else {
				
				isTree = false;
				continue;
			}
			
			//对访问进行标记
			if ( !vist[x] ) {
				
				vist[x] = true;
				node++;
			}
			
			if ( !vist[y] ) {
				
				vist[y] = true;
				node++;
			}
			
			edge++;
			
		} while ( scanf("%d%d", &x, &y), x );//为0表示一个测例结束
		
		printf("Case %d is ", ++t);
		//如果node > edge + 1则是一个森林(多个根结点)
		if ( isTree && node == edge + 1 ) puts("a tree.");
		else puts("not a tree.");//森立不是树,也应该排除
	}
	
	return 0;
}
无注释代码:

#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXN		15

using namespace std;

char	fath[MAXN];
bool	vist[MAXN];

int
find(int x) {

	if ( x == fath[x] ) return x;

	return fath[x] = find( fath[x] );
}

int
main() {

	int		t;
	int		x, y;

	int		i;

	int		node;
	int		edge;

	bool	isTree;

	t = 0;
	while ( scanf("%d%d", &x, &y), x >= 0 ) {
	
		if ( !x ) {
		
			printf("Case %d is a tree.\n", ++t);
			continue;
		}

		memset(vist, false, sizeof(vist));
		for ( i = 0; i < MAXN; i++ ) fath[i] = i;

		node = 0;
		edge = 0;

		isTree = true;

		do {
		
			if ( !isTree ) continue;

			if ( x == y ) {

				isTree = false;
				continue;
			}

			if ( find(y) == y ) fath[y] = find(x);
			else {
				
				isTree = false;
				continue;
			}

			if ( !vist[x] ) {

				vist[x] = true;
				node++;
			}

			if ( !vist[y] ) {
			
				vist[y] = true;
				node++;
			}

			edge++;

		} while ( scanf("%d%d", &x, &y), x );

		printf("Case %d is ", ++t);
		if ( isTree && node == edge + 1 ) puts("a tree.");
		else puts("not a tree.");
	}

	return 0;
}

简单入度计算:

注释代码:

/*                 
 * Problem ID : POJ 1308 Is It A Tree?    
 * Author     : Lirx.t.Una                 
 * Language   : C++            
 * Run Time   : 0 ms                 
 * Run Memory : 152 KB                 
*/

#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXN	15

using namespace std;

char	deg[MAXN];//各个点的入度
bool	vis[MAXN];

int
main() {
	
	int		t;
	int		u, v;
	
	int		node;
	int		edge;
	
	bool	isTree;
	
	t = 0;
	while ( scanf("%d%d", &u, &v), u >= 0 ) {
		
		if ( !u ) {
			
			printf("Case %d is a tree.\n", ++t);
			continue;
		}
		
		memset(deg, 0, sizeof(deg));
		memset(vis, false, sizeof(vis));
		
		node = 0;
		edge = 0;
		
		isTree = true;
		
		do {
			
			if ( !isTree ) continue;
			
			if ( u == v ) {
				
				isTree = false;
				continue;
			}
			
			if ( ++deg[v] > 1 ) {//如果入度大于1则不是树
				
				isTree = false;
				continue;
			}
			
			if ( !vis[u] ) {
				
				vis[u] = true;
				node++;
			}
			
			if ( !vis[v] ) {
				
				vis[v] = true;
				node++;
			}
			
			edge++;
			
		} while ( scanf("%d%d", &u, &v), u );
		
		printf("Case %d is ", ++t);
		if ( isTree && node == edge + 1 ) puts("a tree.");
		else puts("not a tree.");
	}
	
	return 0;
}
无注释代码:

#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXN	15

using namespace std;

char	deg[MAXN];
bool	vis[MAXN];

int
main() {

	int		t;
	int		u, v;

	int		node;
	int		edge;

	bool	isTree;

	t = 0;
	while ( scanf("%d%d", &u, &v), u >= 0 ) {

		if ( !u ) {
		
			printf("Case %d is a tree.\n", ++t);
			continue;
		}

		memset(deg, 0, sizeof(deg));
		memset(vis, false, sizeof(vis));

		node = 0;
		edge = 0;

		isTree = true;

		do {
		
			if ( !isTree ) continue;

			if ( u == v ) {
			
				isTree = false;
				continue;
			}

			if ( ++deg[v] > 1 ) {
			
				isTree = false;
				continue;
			}

			if ( !vis[u] ) {
			
				vis[u] = true;
				node++;
			}

			if ( !vis[v] ) {
			
				vis[v] = true;
				node++;
			}

			edge++;

		} while ( scanf("%d%d", &u, &v), u );

		printf("Case %d is ", ++t);
		if ( isTree && node == edge + 1 ) puts("a tree.");
		else puts("not a tree.");
	}

	return 0;
}
单词解释:

sequentially:adv, 从而,依次地

correspond:vi, 符合,相一致

arrowhead:n, 箭头

property:n, 属性

satisfy:vt, 满足,满足...(条件)

directed:adj, 定向的,有向的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值