您的位置:首页 > 其它

洛谷P2661 信息传递

2018-03-09 20:25 211 查看

☞信息传递☜

大意

有nn个人,每轮每个人ii,当有一个人知道了自己的信息结束,问最多能持续几轮?

数据范围

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

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

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

思路

求最小环,通过并查集实现。有点类似银河英雄传说的思想,只不过更简单了。

如果有两个点的祖先节点相同,那么就可以构成一个环,这个环的长度就是这两个点的路径长度+1

结束的轮数,也就是图中最小环的长度。

代码(数组求长度)

#include<cstdio>
#define t(a) (a<<3)+(a<<1)+c-48//输入流用的
#define r(i,a,b) for(int i=a;i<=b;i++)//a到b
using namespace std;
int f[200001],n,b[200001],ans=0x7fffffff;//初始化
int min(int x,int y){return x<y?x:y;}//最小值函数
int find(int x)
{
if(f[x]!=x)
{
int y=f[x];//先保存
f[x]=find(f[x]);//找祖宗
b[x]+=b[y];//连接
}
return f[x];//返回
}
void judge(int x,int y)//合并
{
int X=find(x),Y=find(y);//找祖宗
if(X!=Y) {f[X]=f[Y];b[x]=b[y]+1;}//更新,连接
else ans=min(ans,b[x]+b[y]+1);//形成环,保存
}
int read()
{
char c;int f=0;
while((c=getchar())<48||c>57);f=t(f);
while((c=getchar())>=48&&c<=57) f=t(f);
return f;//输入流不解释
}
int main()
{
n=read();r(i,1,n) f[i]=i;//初始化
r(i,1,n)
judge(i,read());//合并
printf("%d",ans);//输出
}


代码(递归求长度)

#include <cstdio>
#define maxn 101;
using namespace std;
int f[200001],fa[200001],a[200001],n,ans=2147483647,k=0;
int min(int x,int y)
{
return x<y?x:y;
}
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i]=fa[i]=i;//初始化
}
for (int i=1;i<=n;i++)
{
k=1;//初始长度为1
int u=find(i),v=find(a[i]);
if(u==v)
{
for(int j=a[i];j!=i;j=fa[j])
k++;//求长度
ans=min(ans,k);//保存
}
else
{
fa[i]=a[i];
f[u]=v;//合并
}
}
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: