codevs 4511 信息传递 NOIP2015 day1 T2

来源:互联网 发布:linux ntp客户端 编辑:程序博客网 时间:2024/05/28 17:06

2017.02.18队内胡策(二) 信息传递

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

样例输入 Sample Input
5
2 4 2 3 1

样例输出 Sample Output
3

思路
在输入时将每个点的入度保存,若某点入度为0,则它不能获取别人的生日,在游戏中不起作用,删去,例如样例中的5号;将5号删去后,1号入度也为0,删去,2号入度减一变为一;
以此类推,将入度为0的点放入队列中,依次弹出队首元素,则将next【i】入度减一,若next入度变为0,入队;
队列操作完毕后,剩余若干个环,则最短环长度即答案;

//正解 #include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>const int maxn=200000+5;using namespace std;queue<int> Q;int next[maxn],ru[maxn],vis[maxn];int n,i,j,ans,tot;int main(){    scanf("%d",&n);    ans=maxn;    for(i=1;i<=n;i++){        scanf("%d",&next[i]);        ru[next[i]]++;    }    for(i=1;i<=n;i++){        if(ru[i]==0)        Q.push(i);    }    while(!Q.empty())    {        int u=Q.front();        Q.pop();        ru[next[u]]--;        if(!ru[next[u]])//这里只把入度变为0的点继续压入队列            Q.push(next[u]);    }    for(i=1;i<=n;i++){        if(ru[i]==1&&vis[i]==0){            tot=0;            vis[i]=1;            for(j=next[i];j;j=next[j]){                tot++;                vis[j]=1;                if(j==i) {                ans=min(ans,tot);                     break;                }            }        }    }    printf("%d",ans);    return 0;}
//t两个点以及手抖没打文件操作的暴力#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>const int maxn=200000+5;using namespace std;int n,ans,i,j,tot;int next[maxn],ru[maxn],totl[maxn];bool b[maxn],sum[maxn];int main(){    scanf("%d",&n);    ans=n;    for(i=1;i<=n;i++){        scanf("%d",&next[i]);    }        for(i=1;i<=n;i++){            if(sum[i]==0) {                for(int p=1;p<=n;p++){                    totl[p]=0;//一定记得要清空啊!!                    b[p]=0;                }                tot=0;                sum[i]=1;                b[i]=1;                for(j=next[i];j;j=next[j]){                    tot++;                    sum[j]=1;                    if(b[j]==0) {                        totl[j]=tot;b[j]=1;                    }                    else if(b[j]==1) {                          ans=min(ans,tot-totl[j]);                        break;                    }                }            }        }    printf("%d",ans);    return 0;}
0 0