zoukankan      html  css  js  c++  java
  • 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述

    有n个同学(编号为1到n)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学。

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

    输入输出格式

    输入格式:

    输入共2行。

    第1行包含1个正整数n表示n个人。

    第2行包含n个用空格隔开的正整数T1,T2,……,Tn其中第i个整数Ti示编号为i

    的同学的信息传递对象是编号为Ti的同学,Ti≤n且Ti≠i

    数据保证游戏一定会结束。

    输出格式:

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

    输入输出样例

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

    说明

    样例1解释

    游戏的流程如图所示。当进行完第 3 轮游戏后, 4 号玩家会听到 2 号玩家告诉他自

    己的生日,所以答案为 3。当然,第 3 轮游戏后, 2 号玩家、 3 号玩家都能从自己的消息

    来源得知自己的生日,同样符合游戏结束的条件。

    对于 30%的数据, n ≤ 200;

    对于 60%的数据, n ≤ 2500;

    对于 100%的数据, n ≤ 200000。

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<vector>
     6 #define INF 0x3f3f3f3f
     7 using namespace std;
     8 vector<int> G[500005],rG[500005],vs;
     9 int N,tot=INF,ans,used[500005],cmp[500005],dep[500005],rank[500005],pa[500005];int k=0;
    10 //并查集 
    11 void init_bingchaji(){
    12     for(int i=1;i<=200000;i++){
    13         rank[i]=0;pa[i]=i;
    14     }
    15 }
    16 int Find(int a){
    17     if(pa[a]==a) return a;
    18     else return pa[a]=Find(pa[a]);
    19 }
    20 void unite(int a,int b){
    21     int ta=Find(a),pb=Find(b);
    22     if(rank[ta]>rank[pb]) pa[pb]=ta;
    23     else{
    24         pa[ta]=b;
    25         if(rank[ta]==rank[pb]) rank[pb]++;
    26     }
    27 }
    28 
    29 //强联通分量
    30 void init_qingliantong(){
    31     ;
    32 }
    33 void add_edge(int a,int b){
    34     G[a].push_back(b);
    35     rG[b].push_back(a);
    36 }
    37 void dfs(int v){
    38     used[v]=1;
    39     for(int i=0;i<G[v].size();i++){
    40         if(!used[G[v][i]]) dfs(G[v][i]);
    41     }
    42     vs.push_back(v);
    43 }
    44 void rdfs(int v,int k,int depth){
    45     used[v]=1;
    46     dep[v]=depth;
    47     cmp[v]=k;
    48     for(int i=0;i<rG[v].size();i++){
    49         if(!used[rG[v][i]]) rdfs(rG[v][i],k,depth+1);
    50         
    51         int& now=rG[v][i];
    52         if(cmp[v]==cmp[now]&&Find(v)==Find(now)){
    53             for(int j=0;j<G[v].size();j++){
    54 //                printf("v=%d G[v][j]=%d 
    ",v,G[v][j]);
    55                 if(Find(now)==Find(G[v][j])){
    56                     tot=min(tot,dep[G[v][j]]-dep[v]+1);
    57 //                    printf("%d %d
    ",v,G[v][j]);
    58                 }
    59             }
    60         }
    61         else unite(v,rG[v][i]);
    62     }
    63     for(int i=0;i<rG[v].size();i++){
    64         if(cmp[v]==cmp[rG[v][i]]) continue;
    65         
    66     }
    67 }
    68 void scc(){
    69     for(int i=1;i<=N;i++){
    70         if(!used[i]) dfs(i);
    71     }
    72 //    for(int i=0;i<vs.size();i++) printf("%d ",vs[i]);
    73     memset(used,0,sizeof(used));
    74     init_bingchaji();
    75     for(int i=vs.size()-1;i>=0;i--){
    76         if(!used[vs[i]]) {
    77 //            init_bingchaji();
    78             pa[vs[i]]=vs[i];
    79             rdfs(vs[i],k++,1);
    80         }
    81     }
    82 }
    83 
    84 
    85 int main(){
    86 //    freopen("01.in","r",stdin);
    87     scanf("%d",&N);
    88     for(int i=1;i<=N;i++){
    89         int tmp;scanf("%d",&tmp);
    90         add_edge(i,tmp);
    91     }
    92     scc();
    93 //    for(int i=1;i<=5;i++) printf("%d
    ",cmp[i]);
    94     printf("%d
    ",tot);
    95 }

    非常恶心的 强联通

    以下为并查集特别版

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 
     7 using namespace std;
     8 
     9 queue <int>q;
    10 int n,ans,father[200001],vis[200001],ent[200001];
    11 
    12 int main()
    13 {
    14     cin>>n;
    15     ans=n;
    16     int x,i,j;
    17     for(int i=1;i<=n;++i)
    18     {
    19         scanf("%d",&father[i]);
    20         ++ent[father[i]];
    21     }
    22     for(int i=1;i<=n;++i)
    23     {
    24         if(ent[i]==0)
    25         {
    26             q.push(i);
    27             vis[i]=1;
    28         }
    29     }
    30     while(!q.empty())
    31     {
    32         x=q.front();
    33         q.pop();
    34         --ent[father[x]];
    35         if(ent[father[x]]==0)
    36         {
    37             vis[father[x]]=1;
    38             q.push(father[x]);
    39         }
    40     }
    41     for(int i=1;i<=n;++i)
    42     {
    43         if(ent[i]!=0&&vis[i]!=1)
    44         {
    45             vis[i]=1;
    46             j=father[i];
    47             x=1;
    48             while(vis[j]==0)
    49             {
    50                 vis[j]=1;
    51                 j=father[j];
    52                 ++x;
    53             }
    54             if(ans>=x)ans=x;
    55         }
    56     
    57     }
    58     printf("%d",ans);
    59     puts("");
    60     return 0;
    61 }
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    postgre通过sql释放空闲连接
    LeetCode Weekly Contest 255
    响应式编程基础教程:Spring Boot 与 Lettuce 整合
    响应式编程基础教程:Spring Boot 与 R2DBC 整合
    Spring WebFlux 基础教程:WebSocket 使用
    Spring WebFlux 基础教程:参数校验
    Spring WebFlux 基础教程:快速入门
    LeetCode | 46. 全排列
    LeetCode | 买卖股票的最佳时机
    LeetCode | 动态规划_小青蛙跳楼梯
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/5872974.html
Copyright © 2011-2022 走看看