[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树
创世纪 SZP bzoj-3037/2068 Poi-2004
题目大意:给你n个物品,每个物品可以且仅可以控制一个物品。问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物品,而且选取的个数最大。
注释:$1\le n \le 10^6$。
想法:显然,和骑士类似的,是一个基环树森林。如果A物品可以控制B物品,那就有B物品向A物品连边。对于每一个基环树,如果这个基环树是树的话显然变成树形dp入门题,暴力树形dp即可。然后对于基环树来讲,我们依然记录环上两点,分别以这两点为根,然后特判树形dp即可。
最后,附上丑陋的代码... ...
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 1000010
using namespace std;
int n,m,ans,now,tot;
int to[N],nxt[N],head[N],f[N],g[N],fa[N],ra[N],rb[N];
inline void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
int find(int x)
{
return (fa[x]==x)?x:(fa[x]=find(fa[x]));
}
void dfs(int x)
{
int t=1<<30;
g[x]=0;
for(int i=head[x];i;i=nxt[i])
{
if(to[i]!=now)
dfs(to[i]);
g[x]+=max(f[to[i]],g[to[i]]);
t=min(t,max(f[to[i]],g[to[i]])-g[to[i]]);
}
f[x]=g[x]+1-t;
}
int main()
{
scanf("%d",&n);
int a;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(find(a)!=find(i))
{
add(a,i);
fa[fa[a]]=fa[i];
}
else
ra[++m]=a,rb[m]=i;
}
for(int i=1;i<=m;i++)
{
dfs(ra[i]),now=ra[i];
dfs(rb[i]),a=f[rb[i]];
f[ra[i]]=g[ra[i]]+1;
dfs(rb[i]),ans+=max(a,g[rb[i]]);
}
printf("%d",ans);
return 0;
}
小结:基环树dp是一种常见的,树形dp带基环树的处理方法。这里有一个问题(By JhinLzh),问什么输出答案上面的for循环中的第一个dfs有用?明明在第二个dfs中所有的f和g都被更新了,为什么还要dfs?因为在第一个dfs中我们对f是强行负值,这样对于一些叶子节点来讲t值是没有更改的,这就导致f值在最后是一个极小值,这样的f是不会更新答案的。如果不写第一个dfs,使得一些在本不能更新答案的点更新了答案,导致答案错误。所以第一个dfs是必要的。
[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树的更多相关文章
- 【BZOJ3037/2068】创世纪/[Poi2004]SZP 树形DP
[BZOJ3037]创世纪 Description applepi手里有一本书<创世纪>,里面记录了这样一个故事……上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放 ...
- BZOJ_2068_[Poi2004]SZP_树形DP
BZOJ_2068_[Poi2004]SZP_树形DP Description Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工. Byteasar 国 ...
- hdu-----(4514)湫湫系列故事——设计风景线(树形DP+并查集)
湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tot ...
- BZOJ.1576.[Usaco2009 Jan]安全路经Travel(树形DP 并查集)
题目链接 BZOJ 洛谷 先求最短路树.考虑每一条非树边(u,v,len),设w=LCA(u,v),这条边会对w->v上的点x(x!=w)有dis[u]+dis[v]-dis[x]+len的距离 ...
- 创世纪 BZOJ3037 & [Poi2004]SZP BZOJ2068
分析: 树形DP中的一种,基环树DP 针对每一个环跑DP,f[i],g[i]分别表示选或者不选,之后我们注意每次遍历的时候,不要重复遍历. 附上代码: #include <cstdio> ...
- BZOJ3037 创世纪[基环树DP]
实际上基环树DP的名字是假的.. 这个限制关系可以看成每个点有一条出边,所以就是一个内向基环树森林. 找出每个基环树的环,然后对于树的部分,做DP,设状态选或不选为$f_{x,0/1}$,则 $f_{ ...
- Poetize4 创世纪
3037: 创世纪 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 123 Solved: 66[Submit][Status] Description ...
- 为创世纪图书馆(Library Genesis)作镜像
简介 Library Genesis的Wikipedia条目中的介绍是: Library Genesis or LibGen is a search engine for articles and b ...
- 编程哲学之C#篇:01——创世纪
我们能否像神一样地创建一个世界? 对于创建世界而言,程序员的创作能力最接近于神--相对于导演,作家,漫画家而言,他们创建的世界(作品)一旦完成,就再也不会变化,创建的角色再也不会成长.而程序员创建的世 ...
随机推荐
- esp和ebp指针
gdb调试的时候会出现esp和ebp这两个指针,而这两个指针为我们查看栈的情况提供了方便. 简单点说,esp指向栈顶,而ebp指向栈底.例如一段程序: #include <stdio.h> ...
- Android开发中的SQLite事务处理,即beginTransaction()方法
使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTrans ...
- Docker学习系列(一):windows下安装docker(转载)
本文目录如下: windows按照docker的基本要求 具体安装步骤 开始使用 安装远程连接工具连接docker 安装中遇到的问题 Docker的更新 Docker中的jupyter windows ...
- UNIX环境高级编程--1
前期准备: 下载apue3源文件(从apuebook.com上),然后编译(make)之后,得到libapue.a动态链接文件(.o 就相当于windows里的obj文件 .a 是好多个.o合在一起, ...
- DeltaFish 校园物资共享平台 第七次小组会议
DeltaFish 校园物资共享平台 第七次小组会议 一.上周进度报告 前端 娄:和李一起建立前后端交互参数文档,和数据库文档,完成前端页面跳转和图片加载的 bug,Git 上去. 刘:优化前端 ab ...
- python中struct.pack()函数和struct.unpack()函数
python中的struct主要是用来处理C结构数据的,读入时先转换为Python的字符串类型,然后再转换为Python的结构化类型,比如元组(tuple)啥的~.一般输入的渠道来源于文件或者网络的二 ...
- MySQL主从备份配置
MySQL主从热备配置 两台服务器的MySQL版本都是5.5.41master:192.168.3.119slave:192.168.3.120 MySQL主服务器配置:1.创建用于备份的用户 gra ...
- AjaxDemo
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- Power Designer逆向操作(从mysql5.0生成数据库的物理模型)
Power Designer逆向操作(从mysql5.0生成数据库的物理模型) 环境:powderdesigner12.5:mysql5.0 步骤: 1. 为指定的数据库配置MySQL的ODBC数据 ...
- C# 获得Properties下的定义的资源
var str1 = Properties.Resources.ResourceManager.GetObject("String1", null); string url = S ...