[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带基环树的处理方法。

原文地址:https://www.cnblogs.com/ShuraK/p/8890527.html

时间: 2024-10-09 15:20:59

[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树的相关文章

BZOJ_2068_[Poi2004]SZP_树形DP

Description Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工. Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过的特工. 但是这项任务是如此的机密以至于所有参加行动的特工都必须至少被另一名没有参加任务的特工所监视( 就是说如果某个特工参加了行动,那么原先监视他的那些特工中至少要有一个没有参加进行动). 给出监视任务的详情,要求计算最多能有多少个特工参与其中. Input 第一行只有一个整数, n – 特工的总数,

hdu-----(4514)湫湫系列故事——设计风景线(树形DP+并查集)

湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 3105    Accepted Submission(s): 562 Problem Description 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,

bzoj3037: 创世纪

Description applepi手里有一本书<创世纪>,里面记录了这样一个故事……上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放到一个新的空间中去以建造世界.每种世界元素都可以限制另外一种世界元素,所以说上帝希望所有被投放的世界元素都有至少一个没有被投放的世界元素能够限制它,这样上帝就可以保持对世界的控制.由于那个著名的有关于上帝能不能制造一块连自己都不能举起的大石头的二律背反命题,我们知道上帝不是万能的,而且不但不是万能的,他甚至有事情需要找你帮忙——上帝希望

codevs1919创世纪

1919 创世纪 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 上帝手中有着N 种被称作"世界元素"的东西,现在他要把它们中的一部分投放到一个新的空间中去以建造世界.每种世界元素都可以限制另外一种世界元素,所以说上帝希望所有被投放的世界元素都有至少一个没有被投放的世界元素能够限制它,这样上帝就可以保持对世界的控制.由于那个著名的有关于上帝能不能制造一块连自己都不能举起的大石头的二律背反命题,我们知道上帝不是万能的

Android创世纪

1. 创建第一个Android应用程序 2. Android应用程序目录结构 3. 运行Android应用程序 1. 创建第一个Android应用程序 New--->Android Project   各参数意义在蓝色问号处点击即可查看 后面的基本是默认, 了解每一页是做什么的即可 src                                                      包--->源文件 gen Generated Java Files                 

创世纪互助之王模式解析,三九软件互助系统开发

制度介绍[注册流程]1.向推荐人购买激活币和排单币,由推荐人登录平台以"点击激活会员"的形式完成注册,注册一个账户需要扣除推荐人1个激活币,激活币100一个.(激活后需要完善资料,姓名,×××号,银行卡号,交易密码)2.用户登录ID默认为手机号,手机号不能重复,所以一个手机号和一个×××只能注册一个账户.杜绝多账号,系统会不定期检测,一经发现过多账号,有权冻结其账户,注册成功后,平台自动发送短信将登录用户名与默认密码发送给新会员[静态收益]1.排单规则:每七天可排单一次,每次排单金额必

创世纪互助之王模式解析,互助系统开发

[注册流程]1.向推荐人购买激活币和排单币,由推荐人登录平台以"点击激活会员"的形式完成注册,注册一个账户需要扣除推荐人1个激活币,激活币100一个.(激活后需要完善资料,姓名,身 份 证 号,银行卡号,交易密码)2.用户登录ID默认为手机号,手机号不能重复,所以一个手机号和一个身 份 证只能注册一个账户.杜绝多账号,系统会不定期检测,一经发现过多账号,有权冻结其账户,注册成功后,平台自动发送短信将登录用户名与默认密码发送给新会员[静态收益]1.排单规则:每七天可排单一次,每次排单金额

创世纪游戏、黄金分割比

创世纪游戏 N个人,参与M轮法案的投票.每个人可以提出任意的法案,提出的法案会放到法案队列中,对于每条法案,每个人有4中决策:一票通过.通过.否决.一票否决.一票通过和一票否决会抵消.通过和否决会抵消.一票否决大于一票通过,一票通过大于否决. 如果法案顺利通过,则执行法案中的条款. 更复杂一些: def main(): rule_q=[] now_state=[[]] while rule_q is not empty: x=rule_q.pop() res=judge(x) if pass(r

JoyOI1940 创世纪

一道基环树+树形\(DP\) 原题链接 显然输入的是内向基环树森林,且我们可以单独考虑每一棵基环树. 既然是基环树,自然先\(dfs\)找环,然后随便找环上的一点\(r\),将其与\(A[r]\)的边断开,建反边,这时就会形成一棵以\(r\)为根的树,且每个点的子节点都是能限制它的元素. 于是我们可以在这棵树上跑树形\(DP\). 定义\(f[x][0]\)表示不投放元素\(x\)的时候,以\(x\)为根的子树中能投放元素的最大值:\(f[x][1]\)表示投放元素\(x\)的时候,以\(x\)