Codeforces Round 928 (Div. 4) G. Vlad and Trouble at MIT 题解 树形dp

2024-05-01 02:28

本文主要是介绍Codeforces Round 928 (Div. 4) G. Vlad and Trouble at MIT 题解 树形dp,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Vlad and Trouble at MIT

题目描述

弗拉迪斯拉夫有个儿子非常想去麻省理工学院。麻省理工学院(摩尔多瓦理工学院)的学生宿舍可以用一棵树来表示,树上有 n n n 个顶点,每个顶点代表一个房间,房间里正好有一个学生。树是一个连通的无向图,有 n n n 个顶点和 n − 1 n-1 n1 条边。

今晚,有三种类型的学生:

  • 想参加派对和玩音乐的学生(标记为 P \texttt{P} P );
  • 想睡觉和享受安静的学生(标记为 S \texttt{S} S );
  • 无所谓的学生(标记为 C \texttt{C} C )。

最初,所有的边缘都是薄墙,允许音乐通过,因此当参加派对的学生放音乐时,每个房间都能听到。但是,我们可以在任何边缘放置一些厚墙–厚墙不允许音乐通过。

学校希望安装一些厚墙,这样每个参加派对的学生都可以播放音乐,而睡觉的学生却听不到。
由于大学在冠名权诉讼中损失惨重,他们要求您找出他们需要使用的最少厚墙数量。

输入描述

第一行包含一个整数 t t t ( 1 ≤ t ≤ 1000 1 \leq t \leq 1000 1t1000 ) - 测试用例数。

每个测试用例的第一行包含一个整数 n n n ( 2 ≤ n ≤ 1 0 5 2 \leq n \leq 10^5 2n105 ) - 树中的顶点数。

每个测试用例的第二行包含 n − 1 n-1 n1 个整数 a 2 , … , a n a_2, \dots , a_n a2,,an ( 1 ≤ a i < i 1 \leq a_i < i 1ai<i ) - 这意味着树中的 i i i a i a_i ai 之间有一条边。

每个测试用例的第三行包含一个长度为 n n n 的字符串 s s s,由字符 P \texttt{P} P S \texttt{S} S C \texttt{C} C 组成,表示学生 i i i 的类型为 s i s_i si

所有测试用例中 n n n 的总和不超过 1 0 5 10^5 105

输出描述

对于每个测试用例,输出一个整数–所需的最小厚壁数。

样例输入

3
3
1 1
CSP
4
1 2 2
PCSS
4
1 2 2
PPSS

样例输出

1
1
2

原题

CF——传送门

代码

#include <bits/stdc++.h>
using namespace std;
#define max_Heap(x) priority_queue<x, vector<x>, less<x>>
#define min_Heap(x) priority_queue<x, vector<x>, greater<x>>
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
const double PI = acos(-1);#define INF 1e9 // 无穷大
const int maxn = 1e5 + 6;
int n;
string s;               // 节点类型
vector<int> edge[maxn]; // 存储从根节点指向子节点的有向边
int dp[maxn][3];        // dp[i][0]表示不接触水流,dp[i][1]表示只接触红色水流,dp[i][2]表示只接触蓝色水流void dfs(int u)
{dp[u][0] = INF; // 初始化为无穷大,便于dp求三种情况最小值if (s[u] != 'S')dp[u][1] = 0;elsedp[u][1] = INF; // 若该节点产生蓝色水流,则无法做到只接触红色水流if (s[u] != 'P')dp[u][2] = 0;elsedp[u][2] = INF; // 若该节点产生红色水流,则无法做到只接触蓝色水流int tot = 0;for (int v : edge[u]){// 深搜,dp从叶子节点往根节点转移dfs(v);dp[u][1] = dp[u][1] + min({dp[v][1], dp[v][2] + 1, dp[v][0]}); // 只接触红色水流所需墙壁和,三种情况,其中只有子节点为蓝色水流需要加一个墙壁dp[u][2] = dp[u][2] + min({dp[v][2], dp[v][1] + 1, dp[v][0]}); // 只接触蓝色水流所需墙壁和,三种情况,其中只有子节点为红色水流需要加一个墙壁tot += dp[v][0];                                               // 无水流经过所需墙壁和}if (s[u] != 'C') // 如果不为'C',则该节点本身能产生水流,所以tot赋值无穷大,表示无法无水流tot = INF;dp[u][0] = min({tot, dp[u][1] + 1, dp[u][2] + 1}); // 该节点无水流的情况有三种:来者无水流,有水流+1个墙壁
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);// 本题策略:将'S'类比蓝色水流,将'P'类比红色水流,它们从叶子节点往根节点流,目的是设置最少墙壁使得蓝色水流和红色水流不交汇int t;cin >> t;while (t--){cin >> n;// 记得清空之前测试中的边for (int i = 1; i <= n; i++){edge[i].clear();}int v;for (int i = 2; i <= n; i++){cin >> v;edge[v].push_back(i);}cin >> s;// 补充无关元素,使下标从1开始一一对应节点s = '0' + s;dfs(1);// 取三者最小值int ans = INT_MAX;for (int i = 0; i < 3; i++){ans = min(ans, dp[1][i]);}cout << ans << '\n';}return 0;
}

这篇关于Codeforces Round 928 (Div. 4) G. Vlad and Trouble at MIT 题解 树形dp的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950505

相关文章

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl

uva 10029 HASH + DP

题意: 给一个字典,里面有好多单词。单词可以由增加、删除、变换,变成另一个单词,问能变换的最长单词长度。 解析: HASH+dp 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

XTU 1233 n个硬币连续m个正面个数(dp)

题面: Coins Problem Description: Duoxida buys a bottle of MaiDong from a vending machine and the machine give her n coins back. She places them in a line randomly showing head face or tail face o

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int