~~~题解~~~

题解:

  观察题面可以很快发现这是一棵基环内向树(然而并没有什么用。。。)

  再稍微思考一下,假设将这个环中的任意一点设为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的更多相关文章

  1. BZOJ 1040: [ZJOI2008]骑士 [DP 环套树]

    传送门 题意:环套树的最大权独立集 一开始想处理出外向树树形$DP$然后找到环再做个环形$DP$ 然后看了看别人的题解其实只要断开环做两遍树形$DP$就行了...有道理! 注意不连通 然后洛谷时限再次 ...

  2. bzoj 1040: [ZJOI2008]骑士 環套樹DP

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1755  Solved: 690[Submit][Status] ...

  3. bzoj 1040: [ZJOI2008]骑士 树形dp

    题目链接 1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3054  Solved: 1162[Submit][S ...

  4. 【洛谷】2607: [ZJOI2008]骑士【树形DP】【基环树】

    P2607 [ZJOI2008]骑士 题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一 ...

  5. 【BZOJ1040】[ZJOI2008]骑士 树形DP

    [BZOJ1040][ZJOI2008]骑士 Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情 ...

  6. [ZJOI2008]骑士(基环树,树形dp)

    [ZJOI2008]骑士 题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的 ...

  7. BZOJ1040: [ZJOI2008]骑士(奇环树,DP)

    题目: 1040: [ZJOI2008]骑士 解析: 假设骑士\(u\)讨厌骑士\(v\),我们在\(u\),\(v\)之间连一条边,这样我们就得到了一个奇环树(奇环森林),既然是一颗奇环树,我们就先 ...

  8. 「树形DP」洛谷P2607 [ZJOI2008]骑士

    P2607 [ZJOI2008]骑士 题面: 题目描述 Z 国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的 ...

  9. ZJOI2008 骑士(树型DP)

    ZJOI2008 骑士 题目大意 给出n个人的战斗力和每个人讨厌的人,然后问最大能有多大的战斗力 solution 简单粗暴的题意,有一丢丢背包的感觉 那敢情就是DP了 有点像没有上司的舞会,,, 根 ...

随机推荐

  1. virtual box 故障修复

    vmware ,virtual box等虚拟化环境为一台系统同时允许运行多台系统成为可能准备了技术支持. 通过软件化的平台虚构出硬件设备的驱动,可谓虚拟化技术应用非常广泛. 在平常的虚拟机启动过程中经 ...

  2. 吐血分享:QQ群霸屏技术教程2017(维护篇)

    排名上去,并不是终极稳定,日常维护相当重要. 群排名做上去了,如果不去维护,排名很可能会下去,尤其是咱们做了很多群的时候,完全不会留意到. 为什么不稳定? 1.活跃度下去了,排名当然不稳定,这个需要日 ...

  3. Mysql基础2-数据定义语言DDL

    主要: 数据库操作语句 数据表操作语句 视图定义语句 数据库表设计原则 DDL: Data Definition Language 数据定义语言 数据库操作语句 创建库 创建数据库: create d ...

  4. Python学习手册之函数和模块

    在上一篇文章中,我们介绍了 Python 的控制结构,现在我们介绍 Python 函数和模块. 查看上一篇文章请点击:https://www.cnblogs.com/dustman/p/9976234 ...

  5. 关于C++类模板无法解析的问题

    自己写了一个C++模板类,可是在vs2012中死活显示无法解析它的成员函数. 开始怎么也想不通,因为我是按照普通方式布置的:头文件放声明,在同名源文件中放实现,并包含其头文件. 后来百度了一下才发现, ...

  6. 基于jersey和Apache Tomcat构建Restful Web服务(一)

    基于jersey和Apache Tomcat构建Restful Web服务(一) 现如今,RESTful架构已然成为了最流行的一种互联网软件架构,它结构清晰.符合标准.易于理解.扩展方便,所以得到越来 ...

  7. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  8. js解决img标签加载失败显示默认图片

    问题: 为所有显示楼盘的页面添加一个加载失败的默认图片. 基本思路: img标签中有个onerror属性,专门用来处理加载失败的事件.所以可以用jquery添加onerror属性,在onerror中加 ...

  9. 【性能监控】虚拟内存监控命令vmstat详解

    一.Vmstat说明 vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程.CPU活动进行监控.vmstat 工具提供了一种低开销的系 ...

  10. 1003 Emergency (25 分)(求最短路径)

    给出N个城市,m条无向边.每个城市中都有一定数目的救援小组,所有边的边权已知.现在给出起点和终点,求从起点到终点的最短路径条数及最短经上的救缓小组数目只和.如果有多条最短路径,则输出数目只和最大的 D ...