Luogu P2661 信息传递

  乍一看题,搜索。

  可以暴力找环,可是我总觉得要超时。

  然后想了一种极其猥琐的打法。

  首先可以想到,没有其他人能传递到的点肯定不在环内。因为没有别人能把生日告诉他,因此他绝对不可能知道自己的生日。

  然后记录每一个点的入度,为0的删除,并删掉与它有边相连的点。如果该点的入度也为0,那么继续重复此操作(其实就是拓扑)。

  然后对剩下的点进行找最小环的操作即可。

  总体复杂度大体为O(n)吧。

  CODE 

#include<cstdio>
#include<iostream>
using namespace std;
inline void read(int &x)
{
    x=0; char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
const int N=200005;
int a[N],r[N],i,j,n,x,tot=1e9,len;
bool f[N];
void dfs(int x)
{
    int k=a[x];
    r[k]--;
    if (!r[k]&&!f[k]) f[k]=1,dfs(k);
}
int main()
{
    read(n);
    for (i=1;i<=n;++i)
    {
        read(a[i]);
        r[a[i]]++;
    }
    for (i=1;i<=n;++i)
    if (!r[i]&&!f[i]) f[i]=1,dfs(i);
    for (i=1;i<=n;++i)
    if (!f[i]) 
    { 
        f[i]=1; 
        len=1; j=a[i]; 
        while (j!=i) f[j]=1,len++,j=a[j]; 
        tot=min(tot,len);
    } 
    printf("%d",tot);
    return 0;
}

 

posted @ 2017-11-26 15:26  空気力学の詩  阅读(150)  评论(0编辑  收藏  举报