首页 > 代码库 > 洛谷 P2661 信息传递 Label:并查集?
洛谷 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:
52 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 \n",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\n",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\n",cmp[i]);94 printf("%d\n",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 }
洛谷 P2661 信息传递 Label:并查集?
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。