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. VS2012 Update 2: 0x80040154 corrupt install when starting the debugger

    使用VS2012開發console program ,发现生成32位的exe文件在別的机上不能正确运行,有文章說update1可以解決這個問題,如下 Setup.exe is not a valid ...

  2. [Luogu] 被污染的河流

    https://www.luogu.org/problemnew/show/P3875 线段树扫描线求矩形面积并 扫描线的线段树有点奇怪,修改的标记不会下传,标记的意义是当前区间被完整地覆盖了多少次, ...

  3. 【説明する】KMP

    KMP是一个困扰我很久的算法,听老师或者是学姐讲了差不多有4次了,但是还是搞不太懂,今天终于,终于,终于搞懂了! ——2017-10-29 Vanora 首先推荐一下KMP详解——July 读罢之后内 ...

  4. MySQL数据分析-(12)表操作补充:字段属性

    大家好,我是jacky朱元禄,很高兴继续跟大家学习MySQL数据分析实战,今天我们分享的主题是表操作补充之字段属性,依照惯例第一部分,jacky先跟大家分享本课时的学习逻辑 (一)学习逻辑 我们说创建 ...

  5. 注解之@RequestParam和@GetMapping

    @RequestParam用来处理Content-Type 为 application/x-www-form-urlencoded编码的内容,将请求参数名映射到方法参数名.在Http协议中,如果不指定 ...

  6. Flask-login Question

    1 未登录访问鉴权页面如何处理? 如果未登录访问了一个作了 login_required 限制的 view,那么 Flask-Login 会默认 flash一条消息,并且将重定向到login_view ...

  7. Java并发指南11:解读 Java 阻塞队列 BlockingQueue

    解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程 ...

  8. IDEA 重复代码快速重构(抽取重复代码快捷键)

    Ctrl+Alt+M 顺带一提,eclipse的快捷键是:Alt+Shift+M;

  9. ArcGIS超级工具SPTOOLS-拓扑错误处理

    1.1  删除线面直线上的点 操作视频: https://weibo.com/tv/v/Hxjgmuv6F?fid=1034:4379388532225679 删除面要素.线要素一条边直线上的点. 1 ...

  10. java 测试框架

    项目开发过程中使用的单元测试框架有Junit.TestNG以及Mockito,Junit和TestNG使用的比较多,Mockito最近才开始使用. TestNG与JUnit的相同点 1. 使用anno ...