K. Kingdom‘s Power,树形dp

Problem - K - Codeforces

time limit per test

2.0 s

memory limit per test

512 megabytes

input

standard input

output

standard output

Alex is a professional computer game player.

These days, Alex is playing a war strategy game. The kingdoms in the world form a rooted tree. Alex's kingdom 1 is the root of the tree. With his great diplomacy and leadership, his kingdom becomes the greatest empire in the world. Now, it's time to conquer the world!

Alex has almost infinite armies, and all of them are located at 1 initially. Every week, he can command one of his armies to move one step to an adjacent kingdom. If an army reaches a kingdom, that kingdom will be captured by Alex instantly.

Alex would like to capture all the kingdoms as soon as possible. Can you help him?

Input

The first line of the input gives the number of test cases, T (1≤T≤105). T test cases follow.

For each test case, the first line contains an integer n (1≤n≤106), where n is the number of kingdoms in the world.

The next line contains (n−1)integers f2,f3,⋯,fn (1≤fi<i), representing there is a road between fiand i.

The sum of n in all test cases doesn't exceed 5×106.

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1), and y is the minimum time to conquer the world.

Example

input

Copy

复制代码
2
3
1 1
6
1 2 3 4 4

output

Copy

复制代码
Case #1: 2
Case #2: 6

解析:

题意:

1号节点为根节点,根节点的军队数量是无线的,从根节点开始派兵,一次走一步,走遍所有的节点,需要多少步。

性质:若一棵子树都多个子树,这先走深度小的子树再走深度深的子树,是最优的;同时还要考虑是从一棵子树返回来走向另一棵子树还是从根节点派兵走

所以先dfs一次找出所有的节点的deep,再dfs找出最终答案;

具体见代码:(这道树形dp感觉跟dp没什么关系)

cpp 复制代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int N = 1e6 + 5;
int n;
vector<pair<int, int>>G[N];
int deep[N];
LL ans;
int d = 0, flg = 0;

int dfs(int x,int fa) {
	deep[x] = deep[fa] + 1;
	if (G[x].size() == 0)return 1;
	for (int i = 0; i < G[x].size(); i++) {
		int j = G[x][i].second;
		int& v = G[x][i].first;
		v=dfs(j, x);
	}
	sort(G[x].begin(), G[x].end());
	return G[x].back().first + 1;
}

void dfs1(int x,int fa) {
	if (G[x].size() == 0) {
		if (flg == 0)ans += deep[x];
		else {
			ans += min(deep[x], d);
		}
		flg = 1;
		d = 0;
		return ;
	}
	for (int i = 0; i < G[x].size(); i++) {
		int j = G[x][i].second;
		d++;
		dfs1(j, x);
		d++;
	}
}
int main() {
	int T,cnt=0;
	scanf("%d", &T);
	while (T--) {
		cnt++;
		scanf("%d", &n);
		for (int i = 0; i <= n; i++)
			G[i].clear();
		for (int i = 2,a; i <= n; i++) {
			scanf("%d", &a);
			G[a].push_back({ 0,i });
		}
		deep[0] = -1;
		dfs(1,0);
		flg = 0, d = 0, ans = 0;
		dfs1(1,0);
		printf("Case #%d: %lld\n",cnt, ans);
	}
	return 0;
}
相关推荐
Bruce_kaizy几秒前
c++图论————图的基本与遍历
c++·算法·图论
l1t4 分钟前
利用小米mimo为精确覆盖矩形问题C程序添加打乱函数求出更大的解
c语言·开发语言·javascript·人工智能·算法
亭上秋和景清6 分钟前
strlen;strcpy ;strcat
算法
_OP_CHEN6 分钟前
【算法基础篇】(三十五)图论基础之最小生成树:从原理到实战,彻底吃透 Prim 与 Kruskal 算法
算法·蓝桥杯·图论·最小生成树·kruskal算法·prim算法·acm/icpc
LYFlied12 分钟前
【算法解题模板】-【回溯】----“试错式”问题解决利器
前端·数据结构·算法·leetcode·面试·职场和发展
拾忆,想起15 分钟前
设计模式:软件开发的可复用武功秘籍
开发语言·python·算法·微服务·设计模式·性能优化·服务发现
lxh011321 分钟前
最长有效括号
数据结构·算法
橙子牛奶糖24 分钟前
Science | 本周最新文献速递
算法·gwas·生物信息学·单细胞测序
皮卡蛋炒饭.27 分钟前
背包问题Ⅱ与二分问题
算法
Code Slacker30 分钟前
LeetCode Hot100 —— 普通数组(面试纯背版)(五)
数据结构·c++·算法·leetcode·面试