【蓝桥2018省赛】小朋友崇拜圈
标签:dfs,枚举
思路:
首先看懂题目,样例中输入的3 4 2 5…这些代表什么,他们代表的是1号同学崇拜3号,2号崇拜4号,题目说可以自己崇拜自己,比如9号就是**自恋狂**,崇拜自己。
要找最大的圈,即要成环才行,最后一个数应该回到开始的那个第一个数,比如2 3 4 5 ,由2开始,经过4 5 3,最后一个数是2,这样搜索结束,可以记录和更新答案
dfs流程:
我们从1开始,把1标记 1指向3,标记3 3指向2,标记2 2—>4—>5—>3—>2,每经过的点都被标记过了,我们发现标记过的点在2又重复了,而且最后一个数的开始的数不相等,可以return了,回溯,他会一步一步回退,沿着来时的路回退,回退过程中没有可以继续搜索的点了,那么最终回退到1,从1为起点的搜索结束,接下来搜索2,直到搜索完毕**,记住回退过程中要恢复状态**
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e5+5;
int a[N];
int sum=-1;
int c;
int vis[N];//记录状态,全局变量默认为0,那么我们设定0为未访问,1为访问过
void dfs(int m,int u)
{
if(c==m){sum=max(sum,u);return;}//第一个和最后一个数字一样,成环了,更新答案,回溯
if(!vis[m]) {vis[m]=1;dfs(a[m],u+1);vis[m]=0;}//vis[m]为0,未访问,进行下一次搜索
if(vis[m])return;//没成环,而且被搜过了,那说明不能形成崇拜圈,回溯
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
c=i;//记录下我们的开始点
vis[i]=1;//状态更改
dfs(a[i],1);//第一个代表我们的i号人崇拜的对象,1代表搜索了1个
vis[i]=0;//恢复状态
}
cout<<sum;
}