noip2015D1T1 信息传递(并查集判环)
2017-11-04 17:01
113 查看
题目描述
有 n 个同学(编号为 1 到 n ) 正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 ii的同学的 信息传递对象是编号为 Ti 的同学。
游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信 息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息, 但是每人只会把信息告诉 一个人,即自己的信息传递对象)。当有人从别人口中得知自 己的生日时,游戏结束。请问该游戏一 共可以进行几轮?
输入格式
输入共2行。 第1行包含1个正整数 n ,表示 n 个人。
第2行包含 n 个用空格隔开的正整数 T1,T2,⋯⋯,Tn ,其中第 i 个整数 Ti 表示编号为 i的同学的信息传递对象是编号为 Ti的同学, Ti≤n 且 Ti≠i 。
数据保证游戏一定会结束。
输出格式
输出共1行,包含1个整数,表示游戏一共可以进行多少轮。
n≤200000
根本没想过dfs就可以看出我对图论的熟悉程度真的很辣鸡了……
显然显然又显然,我们可以发现这是一个判断环的问题。
如图。
根据题意,同一连通块里是不可能出现两个环的(因为每个点出度只能为1)。然而这可能并不是一个连通图,所以仍然是要判断最小环的。
并查集。判环可直接完成,另记录环的长度即可。
是有向图噢///
以及,有向图中一点的父节点是它指向的那个点。
有 n 个同学(编号为 1 到 n ) 正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为 ii的同学的 信息传递对象是编号为 Ti 的同学。
游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信 息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息, 但是每人只会把信息告诉 一个人,即自己的信息传递对象)。当有人从别人口中得知自 己的生日时,游戏结束。请问该游戏一 共可以进行几轮?
输入格式
输入共2行。 第1行包含1个正整数 n ,表示 n 个人。
第2行包含 n 个用空格隔开的正整数 T1,T2,⋯⋯,Tn ,其中第 i 个整数 Ti 表示编号为 i的同学的信息传递对象是编号为 Ti的同学, Ti≤n 且 Ti≠i 。
数据保证游戏一定会结束。
输出格式
输出共1行,包含1个整数,表示游戏一共可以进行多少轮。
n≤200000
根本没想过dfs就可以看出我对图论的熟悉程度真的很辣鸡了……
显然显然又显然,我们可以发现这是一个判断环的问题。
如图。
根据题意,同一连通块里是不可能出现两个环的(因为每个点出度只能为1)。然而这可能并不是一个连通图,所以仍然是要判断最小环的。
并查集。判环可直接完成,另记录环的长度即可。
是有向图噢///
以及,有向图中一点的父节点是它指向的那个点。
#include<bits/stdc++.h> using namespace std; int n; int fa[200002],pre[200002];//fa存第i个点的祖先节点。pre存第i个点的父节点。实则用a数组也可以。但是不知道为什么这样比较快。 int a[200002];//第i个点的指向。 int minn=10000000; inline void read(int &x){ int f=1;x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} x*=f; } inline int find_(int x) { if(x==fa[x]) return x; return(fa[x]=find_(fa[x])); } int main() { read(n); for(int i=1;i<=n;i++) { read(a[i]);fa[i]=pre[i]=i;//第i个点的祖先和爹一开始都看作是自己。 } for(int i=1;i<=n;i++) { int x=find_(i);//找到第i个点的祖先。 int y=find_(a[i]);//第i个点指向的点的祖先。 if(x==y)//如果他们的祖先是一样的,就说明它们在一个环中。具体为什么,看图…… { int ans=1; for(int j=a[i];j!=i;j=pre[j]) ans++;//计算环的长度。for循环看着很玄学,简单地说就是从a[i]->a[i]的后继.....->直至重新回到i,其中i~a[i]这条边没算,所以ans初值是1.由于fa是经过状态压缩的,所以这里不能用它。 minn=min(minn,ans); } fa[x]=y;//合并。 pre[x]=a[i];//这就是,呃……就是这样。 } cout<<minn; return 0; }
相关文章推荐
- [并查集]NOIP 2015 Day1 信息传递
- 【 NOIP2015 DAY1 T2 信息传递】带权并查集
- 【P2661】信息传递【并查集】查找最小环
- SSL2505 2015年NOIP提高组试题 信息传递(并查集,最小环)
- 洛谷P2661 信息传递(带权并查集求有向图最小环)
- noip信息传递(并查集判环)
- NOIp 2015信息传递【tarjan/拓扑/并查集】
- Linux主机上的用户信息传递
- liferay-ui message 给错误信息传递参数
- 洛谷P2661 信息传递 (NOIp2015)
- U-Boot如何向内核传递Flash的分区信息
- 使用postMesssage()实现跨域iframe页面间的信息传递----转载
- JAVA后台 关于如何从后台传递信息在jsp前端页面显示
- 客户端信息MD5加密并传递参数给服务器端
- 当创建网页时,如何把信息从一个页面传递到另一个页面
- 使用Bundle在Activity间传递信息
- 关于android中Activity之间添加信息的传递
- NOIP2015信息传递
- PHP其他页面传递信息的两种方法(1、<form>;2、在连接页面后加变量值)
- 为了让信息在网络世界传递,除了搜索,Google 还做了什么?