思路:
一看题我想到的就是想构树,然后层序遍历,每层遍历完输出一次。
但题目给的例子非常简单,有疑问的是,输入的时候不知道结点是否是按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;
}