zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    【NOIP2016提高A组集训第14场11.12】随机游走
    poj2378 树形DP
    简单博弈论总结加例题解析
    uva11426 欧拉函数应用
    poj3090欧拉函数求和
    lightOJ1370 欧拉函数性质
    hdu4497 正整数唯一分解定理应用
    hdu1215 正整数唯一分解定理应用
    lightoj 1236 正整数唯一分解定理
    素数筛两种方法
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5654708.html
Copyright © 2011-2022 走看看