P2607 [ZJOI2008] 骑士

2023-10-16 07:28
文章标签 骑士 p2607 zjoi2008

本文主要是介绍P2607 [ZJOI2008] 骑士,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

P2607 [ZJOI2008] 骑士

[P2607 ZJOI2008] 骑士 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

文章目录

  • P2607 [ZJOI2008] 骑士
    • 题目大意
    • 思路
    • code

题目大意

给你一个 n n n 个点, n n n 条边的基环树森林。

你可以从中选择若干个点,满足两两之间不存在边相连。

每个点有一个权值,请问最大的权值和是多少。

思路

对于每棵基环树,记录返祖边连接的两个点 x , y x , y x,y

d p x , 0 / 1 dp_{x , 0/1} dpx,0/1 表示点 x x x 选、不选时,以 x x x 为根的子树最大权值和是多少。

显然
d p x , 0 = ∑ y ∈ s o n ( x ) max ⁡ { d p y , 0 , d p y , 1 } d p x , 1 = ∑ y ∈ s o n ( x ) d p y , 0 dp_{x , 0} = \sum_{y \in son(x)} \max \{dp_{y , 0} , dp_{y , 1}\} \newline dp_{x , 1} = \sum_{y \in son(x)} dp_{y , 0} dpx,0=yson(x)max{dpy,0,dpy,1}dpx,1=yson(x)dpy,0
因为 x , y x , y x,y 最多只能有一个选,所以没棵基环树的答案为 max ⁡ { d p x , 0 , d p y , 0 } \max \{dp_{x , 0} , dp_{y , 0}\} max{dpx,0,dpy,0}

把全部基环树的答案加起来就好了

不知道为什么 c++17 开了 O 2 O_2 O2 就 T 了。

code

#include <bits/stdc++.h>
#define fu(x , y , z) for(int x = y ; x <= z ; x ++)
#define LL long long
using namespace std;
const int N = 1e6 + 5;
int n , vis[N] , cnt = 1 , hd[N] , pos , to , flgy;
LL a[N] , dp[N][2] , ans;
struct E {int to , nt;
} e[N << 1];
void add (int x , int y) { e[++cnt].to = y , e[cnt].nt = hd[x] , hd[x] = cnt; }
void dfs1 (int x , int fa) {int y;vis[x] = 1;for (int i = hd[x] ; i ; i = e[i].nt) {y = e[i].to;if (y == fa) continue;if (!vis[y])dfs1 (y , x);else pos = i;}
}
LL dfs (int x , int fa) {int y;dp[x][0] = 0;dp[x][1] = a[x];for (int i = hd[x] ; i ; i = e[i].nt) {y = e[i].to;if (y == fa || i == pos || i == (pos ^ 1)) continue;dfs (y , x);dp[x][0] += max (dp[y][0] , dp[y][1]);dp[x][1] += dp[y][0];}
}
int main () {int x , y;scanf ("%d" , &n);fu (i , 1 , n) {scanf ("%lld%d" , &a[i] , &x);add (i , x) , add (x , i);}LL ans1;fu (i , 1 , n) {if (vis[i]) continue;dfs1 (i , 0);x = e[pos].to , y = e[pos ^ 1].to;dfs (x , 0);ans1 = dp[x][0];dfs (y , 0);ans += max (ans1 , dp[y][0]);}printf ("%lld" , ans);return 0;
}

这篇关于P2607 [ZJOI2008] 骑士的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

P2324 [SCOI2005] 骑士精神

*原题链接* T组测试数据,每组数据给定5x5的矩阵,求将其变为目标矩阵的最小步数。 做法:IDA* 分析:看到这样的数据范围和题目描述就可以想到搜索了,由于任何时候矩阵中只有一个空格,所以我们从空格开始进行搜索,看哪个骑士能转移到这个空格上。由于步数超过15步后输出-1,所以可以迭代加深搜索,但是这样爆搜后交上去会T,所以考虑如何优化。剪枝是剪不了的(至少我没想到哪里可以剪枝),既然已经是

重生奇迹MU敏捷流梦幻骑士

“梦幻骑士”这个职业已经存在于重生奇迹MU中很长时间了,虽然现在已经不算是新职业了,但玩家们对于梦幻骑士的研究和开发一直没有停止过。它作为一个特殊的职业,与传统职业截然不同,拥有着许多独特的玩法。其中,有一种玩法是所有平民玩家的最爱。 敏捷流是目前普遍受欢迎的幻想骑士游戏职业,尤其适合平民玩家选择。它不需要过多的资金投入,只需要将大部分升级点数分配到“敏捷”属性即可。但是,它却能带给玩家出乎意料

白骑士的计算机名词解析之各种“面向”

在软件开发领域,编程范式提供了构建和组织代码的多样化方法,帮助开发者更有效地解决问题、提升系统的质量和可维护性。在这些范式中,“面向”编程的概念尤为重要,它们从不同角度审视和优化程序设计的方式。无论是面向对象编程(OOP)、面向过程编程(POP),还是面向服务编程(SOP),这些不同的编程范式各具特色,满足了不同类型项目和需求的多样化要求。每种编程范式都有其独特的优点和应用场景,但

白骑士的HTML教学高级篇 3.3 SVG与Canvas

在现代网页开发中,矢量图形和动态绘图变得越来越重要。HTML5引入了两种强大的图形技术:SVG(Scalable Vector Graphics)和Canvas,它们分别适用于不同的绘图需求。SVG是一种基于XML的矢量图形标准,非常适合用于需要精确控制的可缩放图形;而Canvas则是一种基于像素的绘图技术,适合用于动态图形和动画。在本篇博客中,我们将探讨如何使用SVG和Canva

Day 27:2596. 检查骑士巡视方案

Leetcode 2596. 检查骑士巡视方案 骑士在一张 n x n 的棋盘上巡视。在 **有效 **的巡视方案中,骑士会从棋盘的 左上角 出发,并且访问棋盘上的每个格子 恰好一次 。 给你一个 n x n 的整数矩阵 grid ,由范围 [0, n * n - 1] 内的不同整数组成,其中 grid[row][col] 表示单元格 (row, col) 是骑士访问的第 grid[row][

【C++题解】1438 - 骑士巡游

问题:1438 - 骑士巡游 类型:递归 深搜 广搜 题目描述: 马在中国象棋以日字形规则移动,给定 n×m 大小的棋盘,以及马的初始位置 (x,y) 和目标位置 (s,t),要求不能重复经过棋盘上的同一个点,计算马至少走多少步可以到达目标位置,所有棋盘保证从初始位置到结束位置一定有路径可达。 输入: 测试数据包含一行,为六个整数,分别为棋盘的大小以及初始位置坐标 n,m,x,y,s

记录一下自己的宏碁暗影骑士电脑的属性

@TOC 前言 没有前言。 参考博文 怎么查自己电脑服务器信息吗,如何查看自己电脑的服务器 一、cmd 看到服务器型号 wmic csproduct get name 查询CPU个数 按照博主的方法,我出现了报错。 在 Windows 上,您可以通过 PowerShell 来执行类似的操作。您可以打开 PowerShell 并输入以下命令: (Get-WmiObje

BZOJ1085. [SCOI2005]骑士精神(IDA*算法)

Description   在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑 士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空 位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步 数完成任务。 Input   第一行有一个正整数T(T<

蓝桥杯算法题:蓝桥骑士

题目描述 小明是蓝桥王国的骑士,他喜欢不断突破自我。 这天蓝桥国王给他安排了 N 个对手,他们的战力值分别为 a_1,a_2,…,a_n,且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战,也可以选择避战。 身为高傲的骑士,小明从不走回头路,且只愿意挑战战力值越来越高的对手。 请你算算小明最多会挑战多少名对手。 输入描述 输入第一行包含一个整数 N,表示对手的个数。 第二行包含 N 个整数

骑士

Code: #include <stdio.h>    int board[8][8] = {0};     int travel(int x, int y) ;       int main(void)    {           int startx, starty;           int i, j;           printf("輸入起始點:");