D. Minimal Height Tree(如何BFS遍历序列使树的高度最小)

Problem - 1437D - Codeforces

 

Monocarp有一棵由n个顶点组成的树,它的根在顶点1。他决定研究BFS(宽度优先搜索),所以他在他的树上运行BFS,从根开始。BFS可以用下面的伪代码来描述。

a = [] # 顶点被处理的顺序
q = Queue()
q.put(1) # 把根放在队列的末尾
while not q.empty():
    k = q.pop() # 从队列中获取第一个顶点
    a.append(k) # 将k添加到顶点访问序列的末尾
    for y in g[k]: # g[k]是顶点k的所有子节点的列表,按升序排序
        q.put(y)
Monocarp对BFS非常着迷,以至于最后,他失去了他的树。幸运的是,他仍然有一个顶点序列,即BFS算法访问的顶点的顺序(伪代码中的数组a)。Monocarp知道每个顶点都被访问过一次(因为它们被放在队列中和从队列中取出都是一次)。此外,他还知道每个顶点的所有子节点都被按升序查看。

Monocarp知道有很多树(在一般情况下)具有相同的访问顺序a,所以他不希望恢复他的树。Monocarp可以接受任何具有最小高度的树。

树的高度是指树的顶点的最大深度,而顶点的深度是指从根到它的路径中的边的数量。例如,顶点1的深度是0,因为它是根,而根的所有子女的深度都是1。

帮助 Monocarp 找到任何具有给定访问顺序 a 和最小高度的树。

输入
第一行包含一个整数 t (1≤t≤1000) - 测试案例的数量。

每个测试用例的第一行包含一个整数 n (2≤n≤2⋅105) - 树中顶点的数量。

每个测试用例的第二行包含n个整数a1,a2,...,an (1≤ai≤n; ai≠aj; a1=1) - BFS算法访问顶点的顺序。

保证测试案例中n的总和不超过2⋅105。

输出
对于每个测试案例,打印给定访问顺序a的树的最小可能高度。

例子
input
3
4
1 4 3 2
2
1 2
3
1 2 3
输出
3
1
1
注意
在第一个测试案例中,只有一棵树具有指定的访问顺序。


在第二个测试案例中,也只有一棵具有给定访问顺序的树。


在第三个测试案例中,一个具有给定访问顺序的最优树如下所示。


题解:

直接根据题意模拟即可,把每一个高度的字节点全部遍历完,就可以做到高度最小,因为每个顶点的所有子节点都被按升序查看,所以我么只要发现当前序列大于前一个说明就要一个新的上层根节点cnt,没有大于就记录这层的节点数目now,如果上层根节点用完了cnt == sum,ans++,根节点就变成了我们记录的节点数目sum = now

#include<iostream>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cstring>
#include<stack>
using namespace std;
long long s[200050];
long long son[200050];
long long a[200050];
void solve()
{
	int n;
	cin >> n;
	for(int i = 1;i <= n;i++)
	cin >> a[i];
	int ans = 1;
	int cnt = 0;
	int sum = 1;
	int now = 0;
	for(int i = 2;i <= n;i++)
	{
		if(a[i] > a[i-1])
		{
			now++;
		}
		else
		{
			cnt++;
			if(cnt == sum)
			{
				ans++;
				sum = now;
				cnt = 0;
			}
		}
	}
	cout<<ans<<"\n";
}
int main()
{
	int t = 1;
	cin >> t;
	while(t--)
	{
		solve();
	}
}
//
//abcdef
//babcdef
//1110011

//

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值