码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3037: 创世纪

时间:2016-07-08 23:04:46      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:

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;
}

 

bzoj3037: 创世纪

标签:

原文地址:http://www.cnblogs.com/ccz181078/p/5654708.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!