1004 Counting Leaves (30)(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

题目大意:通过告诉亲子关系的方式给定一棵树,然后输出每一层的叶节点个数

分析:

可知亲子关系对最终的结果影响不是很大,但由于中间的过程计数还是需要记录部分亲子关系

所以我完全没有建树,而是直接记录了每个节点的层数和该层的叶节点数,节点层数由父节点层数+1得到

反思:

一开始1,3测试点一直过不去

后来发现是因为测试样例可能不是按顺序给的,即:一个节点先于他的父节点被录入

如果是这样,那此时父节点的层数就是未知数,会出现混乱

改进方法:若给定节点的父节点此时未被记录,则定义该节点的层数为100+父节点编号,然后后面再集中处理这些层数大于100的节点。

推荐测试用例:

11 5
5 2 10 7
1 3 5 3 4
3 1 9
10 1 2
9 3 11 12 13

输出:0 1 1 4

代码:

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
#include<map>
#include<list>
#include<set>
using namespace std;
int main()
{
	int n, m, i, j, k, father, ID, flag = 0;
	set<int> f;
	int number[100] = { 1 };//一开始根节点有一个节点,后续树还未建
	map<int, int> tree;
	tree[1] = 0;//ID为01的点在第0层
	cin >> n >> m;
	for (i = 0; i < m; i++)//开始建树
	{
		flag = 0;
		cin >> father >> k;
		if (tree.count(father))flag = 1;
		for (j = 0; j < k; j++)
		{
			cin >> ID;
			if (flag&&tree[father]<100)//父节点已存在
			{
				number[tree[father] + 1]++;//若孩子不重复,则在孩子层number++
				tree[ID] = tree[father] + 1;//记录孩子的层数为父亲层数+1
			}
			else tree[ID] = father + 100;
		}
		if (flag&&tree[father] < 100)number[tree[father]]--;//因为父亲节点非叶节点,所以在父节点层number--
	}
	for (map<int, int>::iterator it = tree.begin(); it != tree.end(); it++)//集中处理层数>100的节点
	{
		while (it->second > 100)//修正直到该节点的层数为正确值
		{
			father = it->second % 100;
			ID = it->first;
			while (tree[father] > 100)//因为该节点的父节点可能层数也>100,所以先找到一个层数<100的祖先节点
			{
				ID = father;
				father = tree[ID] % 100;
			}
			f.insert(father);
			tree[ID] = tree[father] + 1;
			number[tree[ID]]++;
		}
	}
	while (f.size())//将层数曾经>100的父节点所在层叶节点数--
	{
		number[tree[*f.begin()]]--;
		f.erase(f.begin());
	}
	m = n - m;
	for (i = 0; m; i++)//输出
	{
		if (i)cout << ' ';
		cout << number[i];
		m -= number[i];
	}
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值