这个亲戚一样的套路,一样的水;一样的快乐;
菜鸟生成记(11)
最近在死磕最小生成树的K开头的算法;这个算法要用到并查集;我就找了道并查集的题(并查集久闻其大名了,就是懒得学;如今被逼无奈,不会并查集,最小生成树的算法完全看不懂)
这个题嘛!水题。不过对于理解并查集帮助很大;
还发现一道也是找祖先的题;算法思想和并查集和像;我放在最下面了(这一题是我们学校OJ上面的题)
没有什么快乐是水题不能给的,如果有,那就多来几道;
还有就是并查集中有个压缩路径(听着逼格很高);可以简单理解为:缩短集合中所有非祖先元素的找到祖先的步骤;
AC代码(很遗憾,这一题暴力还是不行)
#include<bits/stdc++.h>
using namespace std;
const int N=1e+4+10;
const int M=2e+5+10;
int pre[N]={0};
/*
4 3
1 1 2
1 3 4
1 2 3
*/
int find(int x)
{//找祖先函数
int t=x;
while(pre[t]!=t)//终止条件(祖先元素的存储值是自己的下标)
{
t=pre[t];//循环向高辈分找
}
return t;//返回祖先
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)//初始化
{//最初自己是自己的祖先
pre[i]=i;
}
for(int i=1;i<=m;i++)
{
int z,x,y;
cin>>z>>x>>y;
if(z==1)//合并集合
{ //这一步还有逼格超高的叫法(压缩路径)
//就是在合并集合时,让集合内的所有元素,都指向一个祖先
//这样在后续的找祖先时,一步就能找到祖先;
int t1=find(x);//找到x的祖先
int t2=find(y);//找到y的祖先
pre[y]=t1;//y认x的祖先为自己的祖先
pre[t2]=t1;//y的祖先认x的祖先为自己的祖先
}
else//查找x与y是否隶属于一个祖先
{
int t1=find(x);//找到x的祖先
int t2=find(y);//找到y的祖先
if(t1==t2)//祖先一样
cout<<'Y'<<endl;
else//祖先不一样
cout<<'N'<<endl;
}
}
return 0;
}
算法提高 分分钟的碎碎念
时间限制:1.0s 内存限制:256.0MB
问题描述
以前有个孩子,他分分钟都在碎碎念。不过,他的念头之间是有因果关系的。他会在本子里记录每一个念头,并用箭头画出这个念头的来源于之前的哪一个念头。翻开这个本子,你一定会被互相穿梭的箭头给搅晕,现在他希望你用程序计算出这些念头中最长的一条因果链。
将念头从1到n编号,念头i来源于念头from[i],保证from[i]< i,from[i]=0表示该念头没有来源念头,只是脑袋一抽,灵光一现。
输入格式
第一行一个正整数n表示念头的数量
接下来n行依次给出from[1],from[2],…,from[n]
输出格式
共一行,一个正整数L表示最长的念头因果链中的念头数量
样例输入
8
0 1 0 3 2 4 2 4
样例输出
3
样例说明
最长的因果链有:
1-> 2-> 5 (from[5]=2,from[2]=1,from[1]=0)
1-> 2-> 7 (from[7]=2,from[2]=1,from[1]=0)
3-> 4-> 6 (from[6]=4,from[4]=3,from[3]=0)
3-> 4-> 8 (from[8]=4,from[4]=3,from[3]=0)
数据规模和约定
1< =n< =1000
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e+3+10;
int pre[N]={0};
int find(int x)
{//找祖先函数
int t=x;
int k=0;//记录查找次数
while(pre[t]!=t)//终止条件(祖先元素的存储值是自己的下标)
{
k++;
t=pre[t];//循环向高辈分找
}
return k;//返回查找次数
}
int main()
{
int n,max1=-1;
cin>>n;
for(int i=1;i<=n;i++)
cin>>pre[i];//输入i的祖先
for(int i=1;i<=n;i++)
{
int x=find(i);//查找次数
max1=max(x,max1);//记录最大查找次数
}
cout<<max1<<endl;
return 0;
}
这是以前写的;我都忘了写过了(我最近刚看是,看不懂了;尴尬!主要是没注释)
#include<stdio.h>
int main()
{//思路差不多,注释就不写了(懒)
int n;
int a[1001];
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int k,x=1,max=1;
for(int i=n;i>=1;i--)
{
k=i,x=1;
while(a[k])
{
if(a[k]!=0)
{
x++;
k=a[k];
}
}
if(max<x)
max=x;
}
printf("%d",max);
return 0;
}