1004. Counting Leaves (30)

题目如下:

A family hierarchy is usually presented by a pedigree tree. Your job is to count those family members who have no child.

Input

Each input file contains one test case. Each case starts with a line containing 0 < N < 100, the number of nodes in a tree, and M (< N), the number of non-leaf nodes. Then M lines follow, each in the format:

ID K ID[1] ID[2] ... ID[K]
where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID's of its children. For the sake of simplicity, let us fix the root ID to be 01.

Output

For each test case, you are supposed to count those family members who have no child for every seniority level starting from the root. The numbers must be printed in a line, separated by a space, and there must be no extra space at the end of each line.

The sample case represents a tree with only 2 nodes, where 01 is the root and 02 is its only child. Hence on the root 01 level, there is 0 leaf node; and on the next level, there is 1 leaf node. Then we should output "0 1" in a line.

Sample Input
2 1
01 1 02
Sample Output
0 1

这道题简单地说就是对家谱树分层计数,输出每一层的叶子结点的个数,如果想到使用BFS,那么问题也就迎刃而解了。

使用普通的BFS虽然能进行层序遍历,但是并不能知道每一层的开始和结束,这就需要进行算法改进,在BFS基础上增加last和tail两个指针,last和tail的初值为起点,在遍历当前出队结点v邻接点过程中不断的修改tail的值为邻接点的编号,那么在一个顶点的邻接点全部访问完成后,tail指向的便是这一层的最后一个顶点,同时也是下一层的最后一个顶点(当前层是邻接点的根结点所在的层),此后判断当前出队的结点v的值是不是last,如果是,说明到达了这一层的结尾,也就是一层的结束,这时候让last指向下一层的结尾,由上面所述知这个值就存在tail中。特别地,对第一次遍历,因为last的初值为起点,第一次遍历后已经将tail更新为第二层结尾,这时候v=last成立,进入第二层并且更新last为第二层结尾,算法正常运行。

要对每一层的叶子结点进行计数,只需要在输入时多分配一个标志数组isLeaf,在每一层根据邻接点的值对cnt变量计数,然后在进入下一层(v=last)之前输出,注意因为在访问v的邻接点时计数的是下一层的叶子结点数,因此在输出时应该进行处理。

具体的处理方式是,对于第一层,只有0和1两种情况(特别注意只有根的情况,这时候输出为1,这占据了其中一个case),只需要简单的判断输入规模N,如果N=1,那么输出1,否则输出0。

接下来在每个邻接点遍历时对cnt计数,在每次进入下一层之前输出cnt并清零,需要注意的是因为输出的永远是下一层的叶子结点数,如果直接输出,会多输出一个0(到了最后一层又额外输出下一层的),为了防止多输出这个0,可以在这里判断队列是不是为空,如果空则说明BFS即将结束,上次输出的已经是最后一层,不必在输出下一层结果。

AC代码如下:

#include<iostream>
using namespace std;

#define MAX_SCALE 101

int N, M;
bool isLeaf[MAX_SCALE];
bool visited[MAX_SCALE];

typedef struct queue_s *Queue;
struct queue_s{
	int front;
	int rear;
	int data[101];
};

Queue createQueue(){
	Queue q = (Queue)malloc(sizeof(queue_s));
	q->front = q->rear = 1;
	for (int i = 0; i < MAX_SCALE; i++){
		q->data[i] = i;
	}
	return q;
}

bool isEmpty(Queue q){
	return q->front == q->rear;
}

void EnQueue(Queue q,int item){
	q->data[q->rear++] = item;
}

int DeQueue(Queue q){
	if (isEmpty(q)){
		exit(0);
	}
	return q->data[q->front++];
}

void BFS(int root, int map[MAX_SCALE][MAX_SCALE]){

	visited[root] = true;
	Queue q = createQueue();
	EnQueue(q, root);
	int v = 0;
	int tail, last;
	tail = last = root;

	int cnt = 0;

	if (N != 1)
		cout << "0";
	else{
		cout << "1" << endl;
		return;
	}

	while (!isEmpty(q)){

		v = DeQueue(q);
		for (int w = 1; w <= N; w++){
			if (map[v][w] == 1 && !visited[w]){
				visited[w] = true;
				EnQueue(q,w);
				tail = w;
				if (isLeaf[w]){
					cnt++;
				}
			}
		}

		if (v == last && !isEmpty(q)){
			last = tail;
			cout << " " << cnt;
			cnt = 0;
		}
	}

	cout << endl;

}

int main(){

	Queue q = createQueue();

	int map[MAX_SCALE][MAX_SCALE];


	for (int i = 1; i < MAX_SCALE; i++){
		visited[i] = false;
		isLeaf[i] = true;
		for (int j = 1; j < MAX_SCALE; j++){
			map[i][j] = 0;
		}
	}

	cin >> N >> M;

	int root, K, child;
	
	for (int i = 0; i < M; i++){
		scanf("%d%d", &root, &K);
		isLeaf[root] = false;
		for (int j = 0; j < K; j++){
			scanf("%d", &child);
			map[root][child] = 1;
		}
	}

	BFS(1, map);

	return 0;
}


你可能感兴趣的:(算法,bfs,家谱树)