首页 > 其他分享 >P2607 [ZJOI2008] 骑士

P2607 [ZJOI2008] 骑士

时间:2023-10-15 22:16:08浏览次数:39  
标签:基环树 P2607 ZJOI2008 权值 骑士 dp

P2607 [ZJOI2008] 骑士

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

目录

题目大意

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

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

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

思路

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

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

显然

\[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} \]

因为 \(x , y\) 最多只能有一个选,所以没棵基环树的答案为 \(\max \{dp_{x , 0} , dp_{y , 0}\}\)

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

不知道为什么 c++17 开了 \(O_2\) 就 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,权值,骑士,dp
From: https://www.cnblogs.com/2020fengziyang/p/17766289.html

相关文章

  • 骑士:基环树
    https://www.bilibili.com/video/BV1Aa411Q7qp/?spm_id_from=333.999.0.0&vd_source=23dc8e19d485a6ac47f03f6520fb15c2董老师讲的很清楚https://www.luogu.com.cn/problem/P2607 思路:1、深搜找环2、断环成树,对树深搜计算(断边:标记端点或者标记边)O(N)单向边://LuoguP2......
  • hdu 1372 Knight Moves 骑士的移动 bfs--马走日
    #include<stdio.h>#include<string.h>#include<queue>usingnamespacestd;charss[3],ee[3];intx1,y1,x2,y2;structpos{intx,y,step;}sta,end;intf[10][10];intdir[8][2]={1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1};boolfan......
  • P4042 [AHOI2014/JSOI2014] 骑士游戏
    原题非常好的一道题,用到了一个重要的思路:消除\(dp\)的后效性不要觉得这个东西很恐怖,其实这个东西并不复杂,只是名字有点吓人我们容易想到对把原题抽象成一个图,我们容易想到如果该图为\(DAG\)我们要怎么做,直接拓扑上\(dp\)即可但回到原题,我们发现\(dp\)就有了一些问题:这个题是有......
  • 黑魂231 黑骑士建模
    把素材里的c2410材料导入unity项目的model文件夹里,用一个文件夹放起来。然后把c2410模型放进EnemyHandle里,取消ybot。接着将c2410的material的材质包都选上,里面的shader改成有Specularsetup的选项。把对应的材质原图和光影图放进去。 把贴图和法线素材放进Textures文件夹......
  • 【题解】Luogu[P2607] [ZJOI2008] 骑士
    题目说给定\(n\)个点\(n\)个关系,也就是\(n\)条边,显然是基环树,又因为没有规定一定连通,于是我们可以将题目简化为给定一个基环树森林,点有点权,相邻的两个点不能同时选,问最大点权和。part1我们先考虑如果没有环,只是树,该怎么做。这一部分很简单,令\(f_{i,0/1}\)表示以\(i\)......
  • [AHOI2014/JSOI2014] 骑士游戏
    [AHOI2014/JSOI2014]骑士游戏观察性质:对于一类怪兽,要么全部使用普通攻击,要么全部使用魔法攻击。若对怪兽\(i\)满足\(s_i>k_i\),则必使用魔法攻击。若按照怪兽的生成关系连有向边建图,则一个环内\(k\)值最小的怪兽必使用魔法攻击。注意到,如果我们已经确定了完全消灭一......
  • NC20477 [ZJOI2008]树的统计COUNT
    题目链接题目题目描述一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作:I.CHANGEut:把结点u的权值改为tII.QMAXuv:询问从点u到点v的路径上的节点的最大权值III.QSUMuv:询问从点u到点v的路径上的节点......
  • 骑士周游问题
    1. 算法优化意义   9041.算法是程序的灵魂,为什么有些程序可以在海量数据计算时,依然保持高速计算?2.在Unix下开发服务器程序,功能是要支持上千万人同时在线,在上线前,做内测,一切OK,可上线后,服务器就支撑不住了,公司的CTO对代码进行优化,再次上线,坚如磐石。那一瞬间,你就能感受到程序是......
  • ZJOI2008 树的统计
    这是一道比树链剖分板子还板子的题目。操作:我们将以下面的形式来要求你对这棵树完成一些操作:CHANGEut:把节点\(u\)权值改为\(t\);QMAXuv:询问点\(u\)到点\(v\)路径上的节点的最大权值;QSUMuv:询问点\(u\)到点\(v\)路径上的节点的权值和。注意:从点\(u\)......
  • 《皇家骑士:300自走棋》携手来电科技,达成深度战略合作
    近日,跳跃互娱旗下高热度游戏《皇家骑士:300自走棋》与共享充电宝领域的开创企业《来电科技》达成深度战略合作。皇家骑士和来电科技联合定制充电宝,不但能充分发挥皇家骑士的IP效应,更为充电宝赋予了IP趣味元素,让用户享受到联合定制共享充电服务。本次战略合作,无论是对皇家骑士还是来......