codevs 4511 信息传递 NOIP2015 day1 T2

来源:互联网 发布:建筑设计优化职责 编辑:程序博客网 时间:2024/05/19 18:12

题目描述 Description

有个同学(编号为 1 到)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为的同学的信息传递对象是编号为的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮?

输入描述 Input Description

输入共 2行。 第 1行包含1个正整数n,表示n个人 第 2 行包含n 个用空格隔开的正整数T1 ,T 2 ,……,Tn , 其中第i个整数Ti表示编号为i的同学的信息传递对象是编号为 T i 的同学,Ti≤n 且 Ti≠i。 数据保证游戏一定会结束。

输出描述 Output Description

输出共 1行,包含 1个整数,表示游戏一共可以进行多少轮。

样例输入 Sample Input

5
2 4 2 3 1

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

【输入输出样例 1 说明】
游戏的流程如图所示。当进行完第 3 轮游戏后,4 号玩家会听到 2 号玩家告诉他自己的生日,所以答案为 3。当然,第 3 轮游戏后,2 号玩家、3 号玩家都能从自己的消息来源得知自己的生日,同样符合游戏结束的条件。
对于 30%的数据, ≤ 200;
对于 60%的数据, ≤ 2500;
对于 100%的数据, ≤ 200000。

本题可以用dfs也可以用tarjan水

dfs:
#include<cstdio>#include<cstring>#include<iostream>using namespace std;int n,a[200010],flag[200010],num[200010],ans=999999;void dfs(int x,int step){    if (flag[x]) return;    if (num[x])     {        ans=min(ans,step-num[x]);        flag[x]=1;    }    num[x]=step;    dfs(a[x],step+1);    num[x]=0;    flag[x]=1;}main(){    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d",&a[i]);    for (int i=1;i<=n;i++)     if (!flag[i]) dfs(i,0);    printf("%d",ans);}

tarjan:找强连通分量最小环。

#include<iostream>#include<cstdio>#include<queue>#include<stack>#include<cstring>using namespace std;const int maxn=2333333;struct doubi{    int f,t,d;}edge[maxn];int next[maxn],first[maxn],tot;void build(int f,int t){    edge[++tot].f=f;    edge[tot].t=t;    next[tot]=first[f];    first[f]=tot;}int pre[1245000];int cnt;stack<int> q;int scc_num[maxn];int scc_cnt;int dfs(int u){    int lowu=pre[u]=++cnt;    q.push(u);    for(int i=first[u];i;i=next[i])    {        int v=edge[i].t;        if(!pre[v]){            int lowv=dfs(v);            lowu=min(lowu,lowv);        }        else if(!scc_num[v]){            lowu=min(lowu,pre[v]);        }    }    if(pre[u]==lowu){        scc_cnt++;        while(1){            int v=q.top();            q.pop();            scc_num[v]=scc_cnt;            if(u==v) break;        }    }    return lowu;}int tong[maxn];int main(){    int n,m,ans=0;    cin>>n;    for(int i=1;i<=n;i++){        int a;        scanf("%d",&a);            build(i,a);    }    for(int i=1;i<=n;i++){        if(!pre[i]){            dfs(i);        }    }    for(int i=1;i<=n;i++){        tong[scc_num[i]]++;    }    int temp=100000,t;    for(int i=1;i<=1245000;i++){        if(tong[i]<temp&&tong[i]!=1&&tong[i]){            temp=tong[i];        }    }    cout<<temp<<endl;    return 0;}
4 0
原创粉丝点击