#P1486. 第3题-树上脑子
-
1000ms
Tried: 182
Accepted: 72
Difficulty: 8
所属公司 :
阿里
时间 :2023年8月24日-阿里国际
-
算法标签>树形DP
第3题-树上脑子
思路:树形DP
定义f[i]表示从i点出发所能到达的节点数量,也就是最终输出的答案
我们首先需要去在以i为根的子树中找到节点编号最小的节点u
那么则有状态转移方程f[i]=f[u]+1
如果i是叶子结点,则f[i]=1
从根节点1出发,跑一遍DFS即可,一遍递归一遍处理
代码
C++
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,N=1E5+10;
vector<int>g[N];
int n,m,f[N];
int dfs(int u,int fa){
if(g[u].size()==1&&g[u][0]==fa){ //当前节点为叶子结点
f[u]=1;
return u;
}
int minpoint=1e9;
for(int &x:g[u]){
if(x==fa)continue;
minpoint=min(minpoint,dfs(x,u));
}
f[u]=f[minpoint]+1;
return min(u,minpoint);
}
int main(){
cin>>n;
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1,0);
for(int i=1;i<=n;i++)cout<<f[i]<<" ";
return 0;
}
Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class Main {
static List<List<Integer>> graphs = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 0; i < n + 1; i++) {
graphs.add(new ArrayList<>());
}
for (int i = 0; i < n - 1; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
graphs.get(u).add(v);
graphs.get(v).add(u);
}
int[] min = new int[n + 1];
Arrays.fill(min, Integer.MAX_VALUE);
dfs(1, -1, min);
int[] res = new int[n + 1];
for (int i = 1; i < res.length; i++) {
int k = 1;
int v = i;
while (min[v] != v) {
v = min[v];
k++;
}
res[i] = k;
}
for (int i = 1; i < res.length; i++) {
System.out.print(res[i] + " ");
}
}
private static void dfs(int cur, int p, int[] min) {
for (int son : graphs.get(cur)) {
if (son == p) {
continue;
}
dfs(son, cur, min);
if (min[cur] > Math.min(son, min[son])) {
min[cur] = Math.min(son, min[son]);
}
}
if (min[cur] == Integer.MAX_VALUE) {
min[cur] = cur;
}
}
}
Python
n = int(input())
tree = [[] for _ in range(n+1)]
for _ in range(n-1):
a, b = map(int, input().split())
tree[a].append(b)
tree[b].append(a)
tree[1].append(0) # 这里注意
nums = [0] * (n + 1)
def dfs(fa, cur):
if len(tree[cur]) == 1: # 到了根节点
nums[cur] = 1
return cur
min_val = n + 1
for son in tree[cur]:
if son == fa: continue
min_val = min(min_val, dfs(cur, son))
nums[cur] = nums[min_val] + 1
return min(cur, min_val)
dfs(0, 1)
print(" ".join([str(num) for num in nums[1:]]))
题目内容
小红最近沉迷上了PVZ,尤其喜欢自己设计一些关卡,而在设计关卡时,尤其偏爱传送门(进入门的一端后,会从另一端出现)。
这天,小红又设计了一个关卡,不同于PVZ的平面结构,这个关卡在一棵根节点为1的树上。
树上的每个节点都有一个脑子以及一个传送门,而玩家则是一个僵尸。每个传送门,会将玩家传送到该节点子树中除该节点外编号最小的节点处。
小红想知道,从任意一个节点出发,到叶节点为止,玩家一共能吃到多少脑子?
输入描述
一行一个整数n,表示树上的节点数量。
接下来n−1行,每行两个整数u,v,表示u号节点和v号节点之间有一条边。
1≤n≤105
1≤u,v≤n
输出描述
输出一行,n个整数。第i个数表示从第i个节点出发,可以吃到的脑子数量是多少。
样例
输入
4
1 3
3 2
4 1
输出
2 1 2 1