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

创世纪

时间:2020-06-13 13:09:37      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:格式   pac   算法   问题   etc   ==   its   ons   using   

创世纪

题目描述

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

输入格式

第一行是一个整数\(N\),表示世界元素的数目。
第二行有\(N\)个整数\(A_1, A_2, …, A_N.A_i\)表示第\(i\)个世界元素能够限制的世界元素的编号。

输出格式

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

样例输入

6

2 3 1 3 6 5

样例输出

3

数据范围与约定

对于\(100%\)的数据,\(N≤10^6,1≤Ai≤N,Ai≠i\)

思路:

先建树,发现是基环树森林,先固定各环上\(1\)点,再\(dp2\)

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

#include<cstdio>
#include<set>
#include<bitset>
#include<cmath>
#include<stack>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
# define ll long long
# define read read1<int>()
# define Type template<typename T>
Type inline const T read1(){
    T m=0;
    char k=getchar();
    while((‘0‘>k||k>‘9‘)&&(k!=‘-‘))k=getchar();
    const bool f=(k==‘-‘?1:0);
    if(f)k=getchar();
    while(‘0‘<=k&&k<=‘9‘)m=(m<<3)+(m<<1)+(k^48),k=getchar();
    return f?-m:m;
}
# define fre(k) freopen(k".in","r",stdin);freopen(k".out","w",stdout)
# define ll long long
# define N 1000000
int s,fa[N|1],Top,Beg,ty,ans,dp[N|1][2];
bool vis[N|1];
vector<int>G[N|1];
class Set{
    int fa[N|1];
    public:
        int Find(int x){
            if(x!=fa[x])fa[x]=Find(fa[x]);
            return fa[x];
        }
        void clear(int n){for(int i=1;i<=n;++i)fa[i]=i;}
        bool Union(int u,int v){
            int x=Find(v);
            if(x==u)return 1;
            fa[u]=x;
            return 0;
        }
}w;
set<int>se,en;
void dfs(int n){
    int tm=(en.count(n)&&ty)?0:1000001,tem=0;
    for(int i=0;i<G[n].size();++i){
        dfs(G[n][i]);
        tm=min(tm,dp[G[n][i]][1]-min(dp[G[n][i]][1],dp[G[n][i]][0]));
        tem+=min(dp[G[n][i]][1],dp[G[n][i]][0]);
    }
    dp[n][1]=tem+1;
    dp[n][0]=tem+tm;
    if(se.count(n))dp[n][!ty]=1000001;
}
int main(){
    s=read;
    w.clear(s);
    for(int i=1;i<=s;++i)
        if(w.Union(i,fa[i]=read))
            se.insert(i),en.insert(fa[i]);
        else G[fa[i]].push_back(i);
    for(int i=1;i<=s;++i)
        if(!vis[w.Find(i)]){
            vis[w.Find(i)]=1;
            int tans;
            ty=0;dfs(w.Find(i));tans=min(dp[w.Find(i)][0],dp[w.Find(i)][1]);
            ty=1;dfs(w.Find(i));tans=min(tans,min(dp[w.Find(i)][0],dp[w.Find(i)][1]));
            ans+=tans;
        }
    printf("%d",s-ans);
	return 0;
}

创世纪

标签:格式   pac   算法   问题   etc   ==   its   ons   using   

原文地址:https://www.cnblogs.com/SYDevil/p/13113482.html

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