[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——创世纪
我们能否像神一样地创建一个世界? 对于创建世界而言,程序员的创作能力最接近于神--相对于导演,作家,漫画家而言,他们创建的世界(作品)一旦完成,就再也不会变化,创建的角色再也不会成长.而程序员创建的世 ...
随机推荐
- 使用display:flex;实现垂直水平居中
body,div{margin:0px;padding:0px;} .flex-container{display:flex;height:300px;background-color:#ddd;ju ...
- IE下元素设置百分比的问题
场景:近两天在做一个控件,该控件是一个tab型的,并且该tab有可能是两个tab标签,也有可能是多个tab标签,为了能够适应这种动态需求, 在设置标签宽度的时候,直接用的最外层容器除以tab的个数,然 ...
- Akka源码分析-local-DeathWatch
生命周期监控,也就是死亡监控,是akka编程中常用的机制.比如我们有了某个actor的ActorRef之后,希望在该actor死亡之后收到响应的消息,此时我们就可以使用watch函数达到这一目的. c ...
- AJAX json集合传入Controller后台
HTML代码 <html> <head> <meta http-equiv="Content-Type" content="text/htm ...
- Lua相关回调总结【转】
原文 http://www.zaojiahua.com/lua-callback-functions.html 最近做一个小项目,是用Lua写的,中间用到了很多的回调,基本Cocos中的那几种常用回调 ...
- Java系列学习(八)-继承
1.代码块 (1)在java中,使用 { } 括起来的代码 被称为代码块 (2)分类: A:局部代码块 [局部位置] [作用:用于限定 变量的生命周期] B:构造代码块 [在类中的成员位置,用{}括起 ...
- firefox 附加组件栏安装
firefox 在升级到 30的版本后,发现附加组件栏不兼容了. 搜索组件,add-on bar 会得到一个 new add-on bar的组件,安装完后发现上面不显示ip, 后来才发现,应该安装Th ...
- sublime text3配置插件
之前一直习惯用记事本写代码,懒得用IDE,虽然知道用 IDE效率高一些,不过觉得还是用记事本纯手写代码,比较容易记忆.直到昨天写代码遇到了点问题,截图给师兄看,师兄就问我是不是用记事本写代码,为什么不 ...
- 移动web——bootstrap响应式轮播图
基本介绍 1.bootstrap有轮播图的模板,我们只需要改动下就行. 2.这里我们将介绍桌面版本和移动版本最后是综合版本 桌面版本 1.这里的图片设置是有窍门的,不再去添加img标签,而是作为a标签 ...
- 13、scala模式匹配
1.模式匹配的基础语法 2.对类型进行模式匹配 3.对Array和List的元素进行模式匹配 4.case class与模式匹配 5.Option与模式匹配 1.模式匹配的基础语法 Scala提供了m ...