P14919 [GESP202512 六级] 路径覆盖
·
题目描述
给定一棵有 n 结点的有根树 T,结点依次以 1,2,…,n 编号,根结点编号为 1。方便起见,编号为 i 的结点称为结点 i。
初始时 T 中的结点均为白色。你需要将 T 中的若干个结点染为黑色,使得所有叶子到根的路径上至少有一个黑色结点。将结点 i 染为黑色需要代价 ci,你需要在满足以上条件的情况下,最小化染色代价之和。
叶子是指 T 中没有子结点的结点。
输入格式
第一行,一个正整数 n,表示结点数量。
第二行,n−1 个正整数 f2,f3,…,fn,其中 fi 表示结点 i 的父结点的编号,保证 fi<i。
第三行,n 个正整数 c1,c2,…,cn,其中 ci 表示将结点 i 染为黑色所需的代价。
输出格式
一行,一个整数,表示在满足所有叶子到根的路径上至少有一个黑色结点的前提下,染色代价之和的最小值。
输入输出样例
输入 #1复制运行
4 1 2 3 5 6 2 3
输出 #1复制运行
2
输入 #2复制运行
7 1 1 2 2 3 3 64 16 15 4 3 2 1
输出 #2复制运行
10
说明/提示
对于 40% 的测试点,保证 2≤n≤16。
对于另外 20% 的测试点,保证 fi=i−1。
对于所有测试点,保证 2≤n≤105,1≤ci≤10^9。
思路:
状态:以这个点为根的子树从根到每个叶子节点的路径上都有一个黑色节点,最少的染色代价。
转移:枚举所有子节点,sum+=dp[i],dp[u]=max(c[u],sum);
代码:
#include <bits/stdc++.h>
#include <bits/c++config.h>
#include <ostream>
#include <istream>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <time.h>
#include <ctime>
#include <cstdlib>
#define ll long long
#define ull unsigned long long
#define db double
#define st string
#define ch char
#define bo bool
#define s1 27
#define s2 205
#define s3 2005
#define s4 20005
#define s5 200005
#define s6 2000005
#define s7 20000005
using namespace std;
ll n,dp[s5],c[s5];
vector<int> s[s5];
void dfs(int u){
dp[u]=c[u];
ll sum=0;
for(int i=0;i<s[u].size();i++){
dfs(s[u][i]);
sum+=dp[s[u][i]];
}
if(sum)
dp[u]=min(dp[u],sum);
}
signed main(){
cin>>n;
int f;
for(int i=2;i<=n;i++){
cin>>f;
s[f].push_back(i);
}
for(int i=1;i<=n;i++){
cin>>c[i];
}
dfs(1);
cout<<dp[1];
return 0;
}
更多推荐

所有评论(0)