BZOJ3037: 创世纪

来源:互联网 发布:二叉树的遍历 java 编辑:程序博客网 时间:2024/05/17 07:23

我们可以贪心的分析,每个点的入度如果是0,那么这个点不可能

被用来更新答案,那么我们每次找入度为0的点,将他去掉,如果他连的

点没有被更新过答案,那么更新答案,去掉该点,环的时候最后处理就行了

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <stack>using namespace std;#define maxn 1000020long long b[maxn],in[maxn];long long q[maxn];bool flag[maxn];int n;int main(){    int x,y,cnt;    int t=0;    int h=1;    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%d",&b[i]);        in[b[i]]++;    }    for(int i=1;i<=n;i++)    {        if(!in[i])        {            t++;            q[t]=i;        }    }    int tmp;    int ans=0;    while(h<=t)    {        tmp=q[h];        h++;        if(!flag[tmp]&&!flag[b[tmp]])        {            ans++;            flag[b[tmp]]=1;            in[b[b[tmp]]]--;            if (!in[b[b[tmp]]])            {                t++;                q[t]=b[b[tmp]];            }        }        flag[tmp]=1;    }    for (int i=1,j ; i<=n ; i++ )        if ( !flag[i] )        {            cnt=1;            flag[i]=true;            j=i;            while ( b[j]!=i )            {                flag[b[j]]=true;                cnt++;                j=b[j];            }            ans+=cnt/2;        }    printf("%d",ans);    return 0;}

0 0