codevs1919创世纪

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs1919创世纪相关的知识,希望对你有一定的参考价值。

1919 创世纪

 

 时间限制: 2 s
 空间限制: 128000 KB
 题目等级 : 大师 Master 
题目描述 Description

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

输入描述 Input Description

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

输出描述 Output Description

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

样例输入 Sample Input

6
2 3 1 3 6 5

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

  选择2、3、5 三个世界元素即可。分别有1、4、6 来限制它们。

  对于 30% 的数据,N≤10。
  对于 100% 的数据,N≤106,1≤Ai≤N,不保证Ai≠i。

 

来源:Nescafe VIII

标签上写着树形dp,但是瞎搞搞居然就。。。神了。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 10000003
using namespace std;
bool vis[maxn];
queue<int> q;
int val[maxn],n,rnk[maxn],ans;
int find(int x)
{
    int ret=0;
    while(!vis[x])
    {
        ret++;
        vis[x]=1;
        x=val[x];
    }
    return ret;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&val[i]);
        ++rnk[val[i]];
    }
    for(int i=1;i<=n;++i) 
        if(!rnk[i]) q.push(i);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(vis[val[u]]) continue;
        ans++;
        vis[val[u]]=1;
        if(--rnk[val[val[u]]]==0&&!vis[val[val[u]]]) q.push(val[val[u]]);
     } 
     for(int i=1;i<=n;++i) 
     if(!vis[i]) ans+=find(i)/2;
     printf("%d",ans);
     return 0;
}

大概是拓扑排序的样子。。

以上是关于codevs1919创世纪的主要内容,如果未能解决你的问题,请参考以下文章

如何在另一个片段中使用 YouTubePlayerFragment 加载 YouTubePlayer? (安卓)

使用 ViewModel 和 LiveData 递增变量的简单片段示例 - 变量始终为空

未完成代码存档 codevs 2905

同治光绪之交的九江城

数学建模基于matlab GUI随机节点的生成树含Matlab源码 1919期

线段树模板合集(CodeVS1080 1081 1082 4597)Pascal代码