[CF1065F]Up and Down the Tree_tarjan_树形dp
Up and Down the Tree
题目链接:https://www.luogu.org/problem/CF1065F
数据范围:略。
题解:
我们把每个叶子向它上面$k$个点连边,然后trajan缩点。
表示如果一个$SCC$中的叶子能走到,剩下的就都能。
然后我们就求一个最长的根缀链即可。
代码:
#include <bits/stdc++.h>
#define setIO(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define N 1000010
using namespace std;
char *p1, *p2, buf[100000];
#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
}
struct Graph {
int head[N], to[N << 1], nxt[N << 1], tot;
inline void add(int x, int y) {
to[ ++ tot] = y;
nxt[tot] = head[x];
head[x] = tot;
}
}G1, G2;
int f[21][N];
int dep[N], low[N], cnt, sz[N], F[N], st[N], top, blg[N];
bool vis[N], ins[N];
queue <int> q;
void tarjan(int p) {
dep[p] = low[p] = ++cnt;
vis[p] = ins[p] = true;
st[ ++ top] = p;
for (int i = G1.head[p]; i; i = G1.nxt[i]) {
if (!vis[G1.to[i]]) {
tarjan(G1.to[i]), low[p] = min(low[p], low[G1.to[i]]);
}
else if (ins[G1.to[i]]) {
low[p] = min(low[p], dep[G1.to[i]]);
}
}
if (dep[p] == low[p]) {
blg[0] ++ ;
int t;
do {
t = st[top -- ];
blg[t] = blg[0];
ins[t] = false;
} while(t != p);
}
}
bool lf[N];
void dfs(int p, int fa) {
f[0][p] = fa;
for (int i = 1; i <= 20; i ++ ) {
f[i][p] = f[i - 1][f[i - 1][p]];
}
for (int i = G1.head[p]; i; i = G1.nxt[i]) {
dfs(G1.to[i], p);
}
}
int d[N];
int main() {
// setIO("c");
memset(lf, true, sizeof lf);
int n = rd(), k = rd();
for (int i = 2; i <= n; i ++ ) {
int x = rd();
G1.add(x, i);
lf[x] = false;
}
dfs(1, 1);
for (int i = 2; i <= n; i ++ ) {
if (lf[i]) {
int x = i;
for (int j = 20; ~j; j -- ) {
if (k & (1 << j)) {
x = f[j][x];
}
}
G1.add(i, x);
}
}
tarjan(1);
for (int i = 1; i <= n; i ++ ) {
for (int j = G1.head[i]; j; j = G1.nxt[j]) {
if (blg[i] != blg[G1.to[j]]) {
G2.add(blg[i], blg[G1.to[j]]);
d[blg[G1.to[j]]] ++ ;
}
}
}
for (int i = 2; i <= n; i ++ ) {
if (lf[i]) {
sz[blg[i]] ++ ;
}
}
for (int i = 1; i <= blg[0]; i ++ ) {
F[i] = sz[i];
}
q.push(blg[1]);
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = G2.head[x]; i; i = G2.nxt[i]) {
F[G2.to[i]] = max(F[x] + sz[G2.to[i]], F[G2.to[i]]);
d[G2.to[i]] -- ;
if (!d[G2.to[i]]) {
q.push(G2.to[i]);
}
}
}
int ans = 0;
for (int i = 1; i <= blg[0]; i ++ ) {
ans = max(ans, F[i]);
}
cout << ans << endl ;
// fclose(stdin), fclose(stdout);
return 0;
}
[CF1065F]Up and Down the Tree_tarjan_树形dp的更多相关文章
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- web文件夹上传
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端修改 由于项目使用的是 ...
- [UVa12345] Dynamic len (带 修 )
题意:有n个数编号从0→n-1,两种操作: Q L R:询问编号为L→R-1的数中共有多少种不同的数 M X Y:将编号为X的数改为Y ...
- c实现双向链表
实现双向链表:创建.插入.删除 #include <iostream> #include <stdio.h> #include <string.h> #includ ...
- codeforces722E
CF722E Research Rover Unfortunately, the formal description of the task turned out to be too long, s ...
- Docker安装redis3.2
1.拉取redis3.2镜像 2.使用docker images查看拉去下来的镜像 3.运行容器,命令如下 docker run -p : -v $PWD/data:/data -d redis:3. ...
- 攻防世界RE1 writeup
解题过程 将题目给出的exe文件拖入ida中,查看main函数. 分析函数的逻辑,发现用户需要输出一个字符串,存储到变量v9中.如果v9的值与v5的值相等则会打印unk_413e90中的值,否则打印a ...
- springboot自定义异常RESTful返回异常
1.自定义异常类 package com.zhx.common.exception; import com.zhx.common.model.ErrorCode; /** * @Author: Sim ...
- Linux 下基础命令
Linux:开源 Ubuntu Centos Deepin Debian Linux mint ... 1.省钱 2.省资源 Linux由unix演化而来 Linux:开源 Unix: 闭源 sola ...
- CImage中m_hBitmap!=0弹框报错
见图.查资料说是图片打印出现问题. 我的代码流程主要是:读图到CImage中,然后转移到数组中,将原对象销毁,对图像内容处理后,保存. 原来没问题,在加了参数循环后报错. 考虑到是循环中一些因素初始化 ...
- Qt编写数据可视化大屏界面电子看板5-恢复布局
一.前言 恢复布局这个功能在整个数据可视化大屏界面电子看板系统中非常有用,很多时候不小心把现有布局拖动乱了,(当然如果不想布局被拖动改动,可以修改配置文件中的MoveEnable参数来控制,默认为真表 ...