解法一:建树+广度优先遍历
设计好结点数据结构,边读入边建树,用 Map
保存结点防止重复创建同一编号的结点。建树后进行一次广度优先遍历计算每层的叶子结点数量。
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
in.nextToken();
int N = (int) in.nval;
in.nextToken();
int M = (int) in.nval;
// 处理特殊情况
if (M == 0) {
out.println(N);
out.flush();
return;
}
// 建树
Map<Integer, TreeNode> map = new HashMap();
for (int i = 0, id, cnt; i < M; ++i) {
in.nextToken();
id = (int) in.nval;
in.nextToken();
cnt = (int) in.nval;
TreeNode root = map.getOrDefault(id, new TreeNode(id, cnt));
for (int j = 0, childId; j < cnt; ++j) {
in.nextToken();
childId = (int) in.nval;
TreeNode childNode = map.getOrDefault(childId, new TreeNode(childId));
map.put(childId, childNode);
root.next.add(childNode);
}
map.put(id, root);
}
// 层序遍历
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(map.get(1));
ArrayList<Integer> ans = new ArrayList<>();
while (!queue.isEmpty()) {
int cnt = 0;
int size = queue.size();
for (int i = 0; i < size; ++i) {
TreeNode root = queue.poll();
if (root.next.isEmpty()) {
++cnt;
} else {
for (TreeNode node : root.next) {
queue.offer(node);
}
}
}
ans.add(cnt);
}
for (int i = 0; i < ans.size() - 1; ++i) {
out.print(ans.get(i) + " ");
}
out.println(ans.get(ans.size() - 1));
out.flush();
}
}
class TreeNode {
int id;
List<TreeNode> next;
TreeNode(int id) {
this.id = id;
next = new ArrayList<>();
}
TreeNode(int id, int capacity) {
this.id = id;
next = new ArrayList<>(capacity);
}
}