bzoj3037: 创世纪

Description

applepi手里有一本书《创世纪》,里面记录了这样一个故事……
上帝手中有着N 种被称作“世界元素”的东西,现在他要把它们中的一部分投放到一个新的空间中去以建造世界。每种世界元素都可以限制另外一种世界元素,所以说上帝希望所有被投放的世界元素都有至少一个没有被投放的世界元素能够限制它,这样上帝就可以保持对世界的控制。
由于那个著名的有关于上帝能不能制造一块连自己都不能举起的大石头的二律背反命题,我们知道上帝不是万能的,而且不但不是万能的,他甚至有事情需要找你帮忙——上帝希望知道他最多可以投放多少种世界元素,但是他只会O(2^N) 级别的算法。虽然上帝拥有无限多的时间,但是他也是个急性子。你需要帮助上帝解决这个问题。

Input

第一行是一个整数N,表示世界元素的数目。
第二行有 N 个整数A1, A2, …, AN。Ai 表示第i 个世界元素能够限制的世界元素的编号。

Output

一个整数,表示最多可以投放的世界元素的数目。

1.对一个叶节点,删去它和父节点并把答案+1是最优的(父节点与其它点配对不会更优)

2.对一个含a个点的环(不与其它点相连),对答案的贡献为a>>1

拓扑排序过程中按1.处理,排序后剩下的环按2.处理

#include<cstdio>
const int N=1000010,R=9000000;
bool ed[N];
int n,fa[N],in[N],q[N],ql=0,qr=0,ans=0;
char buf[R],*ptr=buf-1;
inline int _int(){
    int x=0,c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
int main(){
    fread(buf,1,R-4,stdin);
    n=_int();
    for(int i=1;i<=n;i++)++in[fa[i]=_int()];
    for(int i=1;i<=n;i++)if(!in[i])q[qr++]=i;
    while(ql!=qr){
        int w=q[ql++];
        if(ed[w])continue;
        int f=fa[w];
        if(!--in[f])q[qr++]=f;
        ed[w]=1;
        if(!ed[f]){
            ed[f]=1;
            ++ans;
            f=fa[f];
            if(!--in[f])q[qr++]=f;
        }
    }
    for(int i=1;i<=n;i++)if(!ed[i]){
        int c=1,w=fa[i];
        ed[w]=1;
        while(w!=i){
            ++c;
            ed[w]=1;
            w=fa[w];
        }
        ans+=c>>1;
    }
    printf("%d",ans);
    return 0;
}
时间: 2024-08-09 02:04:38

bzoj3037: 创世纪的相关文章

[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树

创世纪 SZP bzoj-3037/2068 Poi-2004 题目大意:给你n个物品,每个物品可以且仅可以控制一个物品.问:选取一些物品,使得对于任意的一个被选取的物品来讲,都存在一个没有被选取的物品,而且选取的个数最大. 注释:$1\le n \le 10^6$. 想法:显然,和骑士类似的,是一个基环树森林.如果A物品可以控制B物品,那就有B物品向A物品连边.对于每一个基环树,如果这个基环树是树的话显然变成树形dp入门题,暴力树形dp即可.然后对于基环树来讲,我们依然记录环上两点,分别以这两

Android创世纪

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

codevs1919创世纪

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

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

制度介绍[注册流程]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

MFC建立应用程序启示录(创世纪新篇)

MFC是vc+的核心部分,需要一定的编程功底. Windows编程基础 编制一个功能强大和易操作的Windows应用程序所需要的代码肯定会比一般的C++程序要多得多,但并不是所有的代码都需要自己从头开始编写,因为Visual C++不仅提供了常用的Windows应用程序的基本框架,而且可以在框架程序中直接调用Win32 API(Application Programming Interface, 应用程序接口)函数.这样,用户仅需要在相应的框架位置中添加自己的代码或修改部分代码就可实现Windo

使用c#开发的第一款APP的Android浏览器(创世纪篇)

闲来无事,利用c#编程语言开发Android浏览器. 首先,安装 VS2010.安装 Android SDK.配置 AVD(android) 模拟器. 调试的时候打开 ADV(android 模拟器) 在里面你自己添加一个机器的型号,设置好分辨率,内存大小,SD卡,启动之后,就可以调试了! 调试生成的代码是不能发布到真实的机器上的,因为 android 实际程序在真实机器中运行的时候会进行验证,这个在 netbeans 或 eclipse 里面叫 key.store 所以发布的时候,要用 net

编程如何入门(创世纪新篇)

万事开头难,人人 都梦想成为像比尔盖茨,乔布斯这样的编程大师,但进入软件开发领域也是很艰难的,就像一个神学院的学生不知如何祷告.当然,如果你还是一名刚刚入门的程序员,那么我相信你深刻理解没有经验或者没有太多经验想找一份工作是如何困难.如果你已经在软件开发这一行干过一段时间,那么我相信想要在这个竞争激烈的行业鹤立鸡群又是如何困难. 我接触过很多刚刚入门的开发人员,他们非常迷茫,因为他们不知道该往哪里投入自己的精力来发展自己的职业生涯,也不知道未来的方向在哪里.选择是如此之多,让人眼花缭乱:有那么多