[ZJOI2008]骑士 DP dfs
题解:
观察题面可以很快发现这是一棵基环内向树(然而并没有什么用。。。)
再稍微思考一下,假设将这个环中的任意一点设为root,然后去掉root到下面的特殊边(即构成环的那条边),那么就构成了一棵树,并且可以用简单树形DP解决。
再考虑加上这条边的限制,设被去掉的这条边是连接root 和 x的, 这条边实际上就是限制了在选root的时候不能选x,那么考虑一个暴力的想法。
我们先在图中dfs,找到这个环,然后任意指定一点为root,再跑两边树形DP,一遍强制不选root,然后跑普通树形DP。另一遍强制选root,然后跑树形DP加上特判不能选x,最后两种答案取max即可。
我这样写可能比较长,别人的做法只要写两遍dfs,我需要3遍(不过后面两个dfs可以复制粘贴)。但实际上是一个思路。别人的做法是dfs找到这个环,然后随便找条环上的边断开,然后强制这条边连接的两个点其中一个不选(其实就和我的写法一样的意思,只不过我是先把这两个点中的一个指定为了root)
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 1000100
#define ac 2000100
#define LL long long
int n, m, root;
int s[AC], p[AC], deep[AC];
LL f[AC][], g[AC][], ans;//存下每个点的厌恶对象以方便判断
int Head[AC], date[ac], Next[ac], tot;
bool z[AC], vis[AC], book[AC], flag; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void add(int f, int w)
{
date[++tot] = w, Next[tot] = Head[f], Head[f] = tot;
date[++tot] = f, Next[tot] = Head[w], Head[w] = tot;
} void pre()
{
n = read();
for(R i = ; i <= n; i ++)
{
s[i] = read(), p[i] = read();
add(i, p[i]);
}
deep[] = ;
} void dfs1(int x)//找到反向边的那个点定为root
{
z[x] = true;
int now;
//if(root) return ;
for(R i = Head[x]; i; i = Next[i])
{
now = date[i];
if(z[now] && deep[now] + != deep[x]) root = x;
if(z[now] && p[now] == x && p[x] == now) root = x, flag = true;//特殊情况
//if(root) return ;
if(z[now]) continue;
deep[now] = deep[x] + ;
dfs1(now);
}
} void dfs2(int x)//强制选root
{
int now;
vis[x] = true;
f[x][] = s[x];//初始化
for(R i = Head[x]; i; i = Next[i])
{
now = date[i];
if(vis[now]) continue;
if(now == p[x] && x == root && !flag) continue;
dfs2(now);//忽略这条边,如果是特殊情况则不能忽略,因为是重边,一旦忽略将忽略2条
f[x][] += f[now][];
f[x][] += max(f[now][], f[now][]);
}
if(x == p[root]) f[x][] = f[x][];
} void dfs3(int x)//强制不选root
{
int now;
g[x][] = s[x];
book[x] = true;
for(R i = Head[x]; i; i = Next[i])
{
now = date[i];
if(book[now]) continue;
if(now == p[x] && x == root && !flag) continue;
dfs3(now);
g[x][] += g[now][];
g[x][] += max(g[now][], g[now][]);
}
} void work()
{
for(R i = ; i <= n; i ++)//因为本来就不一定联通,所以要跑多次
if(!z[i])
{
dfs1(i);
dfs2(root);
dfs3(root);
ans += max(f[root][], g[root][]);
}
printf("%lld\n", ans);
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}
[ZJOI2008]骑士 DP dfs的更多相关文章
- BZOJ 1040: [ZJOI2008]骑士 [DP 环套树]
传送门 题意:环套树的最大权独立集 一开始想处理出外向树树形$DP$然后找到环再做个环形$DP$ 然后看了看别人的题解其实只要断开环做两遍树形$DP$就行了...有道理! 注意不连通 然后洛谷时限再次 ...
- bzoj 1040: [ZJOI2008]骑士 環套樹DP
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1755 Solved: 690[Submit][Status] ...
- bzoj 1040: [ZJOI2008]骑士 树形dp
题目链接 1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3054 Solved: 1162[Submit][S ...
- 【洛谷】2607: [ZJOI2008]骑士【树形DP】【基环树】
P2607 [ZJOI2008]骑士 题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一 ...
- 【BZOJ1040】[ZJOI2008]骑士 树形DP
[BZOJ1040][ZJOI2008]骑士 Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情 ...
- [ZJOI2008]骑士(基环树,树形dp)
[ZJOI2008]骑士 题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的 ...
- BZOJ1040: [ZJOI2008]骑士(奇环树,DP)
题目: 1040: [ZJOI2008]骑士 解析: 假设骑士\(u\)讨厌骑士\(v\),我们在\(u\),\(v\)之间连一条边,这样我们就得到了一个奇环树(奇环森林),既然是一颗奇环树,我们就先 ...
- 「树形DP」洛谷P2607 [ZJOI2008]骑士
P2607 [ZJOI2008]骑士 题面: 题目描述 Z 国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的 ...
- ZJOI2008 骑士(树型DP)
ZJOI2008 骑士 题目大意 给出n个人的战斗力和每个人讨厌的人,然后问最大能有多大的战斗力 solution 简单粗暴的题意,有一丢丢背包的感觉 那敢情就是DP了 有点像没有上司的舞会,,, 根 ...
随机推荐
- 【php练习源码】
Something is wrong with the XAMPP installation :-( value[$name]=$sex; } public function getInfomatio ...
- 第五课:PHP echo和print 语句
PHP echo 和 print 语句 PHP 是通过 print 和 echo 语句来动态输出 HTML 内容,虽然 print 和 echo 语句两者的功能几乎是完全一样,但是还是有一点差别的. ...
- Laravel-admin 当使用Form组件hasMany的时候 进行编辑出现错误 foreach错误的时候解决方案
我的关联关系原名是 goodImage 修改成 image 之后解决问题 分析得出应该是 laravel会将goodImage 转成 good_image字段 这样就foreach会报错 所以出 ...
- hadoop生态搭建(3节点)-01.基础配置
# 基础配置# ==================================================================node1 vi /etc/hostname nod ...
- python3 练习题100例 (二十八)打印一定范围内的素数
题目内容: 给定一个大于2的正整数n,打印出小于n(不包括n且n不大于100)的所有素数. 要求将符合条件的输出填入一个列表中,打印的结果为该列表. 输入格式: 共一行,为一个大于2的正整数 输出格式 ...
- C# 隐藏窗口标题栏、隐藏任务栏图标
//没有标题 this.FormBorderStyle = FormBorderStyle.None; //任务栏不显示 this.ShowInTaskbar = false;
- Java 中编码与摘要算法
URL 编码与解码 String s = "你好,世界!"; // URL 编码 String urlEncodedString = URLEncoder.encode(s, &q ...
- 4368: [IOI2015]boxes纪念品盒
4368: [IOI2015]boxes纪念品盒 链接 分析 链接 代码 #include<bits/stdc++.h> using namespace std; typedef long ...
- Coap协议学习笔记-第一篇
1. 物联网应用上一般使用单片机(或者其他SOC),单片机的RAM内存一般只有20KB~~128KB左右,然而一个TCP协议栈可能就20KB,所以只能用UDP,因为UDP相对小很多,然后在UDP上加了 ...
- Android学习笔记之,调用系统图库,添加自定义字体,屏幕截图
新年开始的第一天就来学习了慕课迎春活动中的Android心愿分享一课,学到了几个知识点,在此记录一下. 1.调用系统图库调用系统图库用的是intent,步骤为弹出系统图库选择器,选择图片后获取到所选择 ...