zoukankan      html  css  js  c++  java
  • P2661 信息传递

    题意:

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

    输入输出样例

    输入样例
    5
    2 4 2 3 1
    输出样例
    3

    说明

    样例1解释

    游戏的流程如图所示。当进行完第3 轮游戏后, 4号玩家会听到 2 号玩家告诉他自己的生日,所以答案为 3。当然,第 3 轮游戏后,2号玩家、 3 号玩家都能从自己的消息来源得知自己的生日,同样符合游戏结束的条件。

    对于 30%的数据, n ≤ 200

    对于 60%的数据, n ≤ 2500

    对于100%的数据, n ≤ 200000

    并查集判最小环

    假设信息由A传递给B,那么就连一条由A指向B的边,同时更新A的父节点,A到它的父节点的路径长也就是B到它的父节点的路径长+1。

    这样我们就建立好了一个图,之后信息传递的所有环节都按照这些路径。游戏结束的轮数,也就是这个图里最小环的长度。

    如果有两个点祖先节点相同,那么就可以构成一个环,长度为两个点到根节点长度之和+1。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    #define olinr return
    #define _ 0
    #define love_nmr 0
    #define DB double
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            x=-x;
            putchar('-');
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    int f[205050];
    int dis[205050];
    int ans=0x7fffffff;
    int n;
    inline int findset(int x)
    {
        if(x!=f[x])
        {
            int fa=f[x];
            f[x]=findset(f[x]);   //路径压缩 
            dis[x]+=dis[fa];    //记录到根的路径长
        }
        return f[x];
    }
    inline void doit(int x,int y)
    {
        int xx=findset(x);   //找到根
        int yy=findset(y);
        if(xx!=yy)   //不在一个集合(不会得到自己生日的信息)
        {
            f[xx]=yy;
            dis[x]=dis[y]+1;
        }
        else
            ans=min(ans,dis[x]+dis[y]+1);  //求最小环长度
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
            f[i]=i;
        for(int i=1;i<=n;i++)
            doit(i,read());
        put(ans);
        olinr ~~(0^_^0)+love_nmr;
    }
  • 相关阅读:
    js rsa sign使用笔记(加密,解密,签名,验签)
    金额的计算
    常用js方法集合
    sourceTree 的使用
    node-- express()模块
    详细讲解vue.js里的父子组件通信(props和$emit)
    Vue -- vue-cli webpack打包开启Gzip 报错
    es6函数的rest参数和拓展运算符(...)的解析
    js中判断对象数据类型的方法
    vue学习之vue基本功能初探
  • 原文地址:https://www.cnblogs.com/olinr/p/9560686.html
Copyright © 2011-2022 走看看