【PAT-A】1004. Counting Leaves 写题记录

思路:

一看题我想到的就是想构树,然后层序遍历,每层遍历完输出一次。

但题目给的例子非常简单,有疑问的是,输入的时候不知道结点是否是按ID的次序输入的,若是按照次序输入,一路构建下来就很容易了,若不是按照次序,我的思路是等所有M个子树都构建完毕,记录子树根结点的地址、ID,然后从ID为1的根节点开始依次连接各个子树。

事实上若是按照次序输入的情况写只能拿到部分正确,有几个测试点是过不去的,改成不按次序的情况就能全部通过了。

#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 110;
struct node {
	int id;
	int level;
	vector<node*> next;  //可变数组用来存子节点 
};

void levelTrave(node* root){ //层序遍历 ,BFS
	int num=0,p=1; //num是每一层的叶子点数,p用来标记当前所在层数,从1开始 
	queue<node*> Q;
	root->level = p;
	Q.push(root);
	while (!Q.empty()){
		node* nownode= Q.front();
		Q.pop();
		if (p+1 == nownode->level){ //如果出队的结点level增加一,说明开始下一层了 
			printf("%d ",num); //输出p层的num,注意最后一层的num是输出不了的 
			num=0; //num重新开始计数 
			p++; //当前层数更新 
		}
		if (nownode->next.size() != 0){ //判断结点有无子结点 
			for (int i=0;i<nownode->next.size();i++){  //有子结点 
				nownode->next[i]->level = nownode->level+1;  //子结点的层数更新后再入队 
				Q.push(nownode->next[i]);
			}
		}else { //没有结点的话说明示叶子结点,num增加 
			num++;
		}
	}
	printf("%d",num);

	return;	
}

void insert(node* &root, int id, node* nodes){  //插入子树 
	if (root->id == id){  //找到id就连接,因为是依ID的次序,所以不存在找不到的情况
		root = nodes;
	}

	for (int i=0; i<root->next.size(); i++){ //找不到就往子树找 
		insert(root->next[i], id, nodes);
	}
	
}

int main(){
	int n, m;
	scanf("%d%d",&n,&m);
	node*v[maxn] = {0};
	node* root = new node;  //设置ID为1的根节点 
	root->id = 1;	
	for (int i=0; i<m; i++){
		int id, k;
		scanf("%02d%d",&id,&k);  
		node* nodes = new node;  //创建子树的根结点 
		nodes->id = id;
		v[id] = nodes;  //以子树的ID为下标,保存子树根结点地址 
		for (int j=0; j<k; j++){  //将子树加入 
			node* child = new node;
			int child_id;
			scanf("%02d",&child_id);
			child->id = child_id;
			nodes->next.push_back(child);
		}
	}
	for (int i=1; i<=n;i++){  //ID从小到大连接子树,注意i<=n,不是<=m 
		if (v[i]!=0){
			insert(root,i,v[i]);
		}
	}
	levelTrave(root);
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/weixin_43456345/article/details/83309153