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的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  3. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  4. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  5. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  6. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  7. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  8. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

  9. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

随机推荐

  1. Start Failed, Internal error: recovering IDE to the working state after the critical startup error

    Start Failed, Internal error: recovering IDE to the working state after the critical startup error F ...

  2. AtomicInteger如何保证线程安全以及乐观锁/悲观锁的概念

    众所周知,JDK提供了AtomicInteger保证对数字的操作是线程安全的,线程安全我首先想到了synchronized和Lock,但是这种方式又有一个名字,叫做互斥锁,一次只能有一个持有锁的线程进 ...

  3. Oracle 三种连接方式 NESTED LOOP HASH JOIN SORT MERGE JOIN

    NESTED LOOP: 对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择.在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不能太大( ...

  4. python print import使用

    >>> print("aaaa","bbbb")aaaa bbbb>>> print(1, 2, 3)1 2 3 为模块提供 ...

  5. [Luogu] 最小差值生成树

    https://www.luogu.org/recordnew/show/6125570 思路就是巧妙的枚举所有的生成树,取最优值首先按照边权排序找出第一颗最小生成树(l, r),其中l表示最小边的编 ...

  6. Appium Inspector定位Webview/H5页面元素

    目录 操作步骤 Python操作该混合App代码 Appium在操作混合App或Android App的H5页面时, 常常需要定位H5页面中的元素, 传统方式是 翻墙 + 使用Chrome://ins ...

  7. python爬虫demo01

    python爬虫demo01 1 import requests, json, time, sys 2 from bs4 import BeautifulSoup 3 from contextlib ...

  8. 数据分析之numpy使用

    使用numpy生成数字 生成的类型是ndarray类型 t1 = np.array([1,2,3,4,5]) print(t1,type(t1)) # 类型为ndarray t2 = np.array ...

  9. Python学习日记(三)——Python基本数据类型(运算符、int、str、tuple、dict、range)

    运算符 1.算数运算 2.比较运算 3.赋值运算 4.逻辑运算 5.成员运算 基本数据类型 1.数字 int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2 ...

  10. SpringBoot RestTemplate接收文件,并将文件发送到另外一个程序进行存储

    最近有个需求,接收用户上报的证书,并且保存起来,证书大小不到1M,但该证书的保存必须在另外一个程序进行,所以想到使用springboot接收上传文件后,再通过RestTemplate将文件发送给另外一 ...