牛客3007B-图-记忆化搜索

链接:https://ac.nowcoder.com/acm/contest/3007/B
来源:牛客网

题目描述:

现在有一个N个点的有向图,每个点仅有一条出边
你需要求出图中最长的简单路径包含点的数量
(1≤N≤1,000,000)

输入描述:

第一行一个数字N
接下来N行,每行一个正整数,第i+1行的数字表示第i个点出边终点的编号
(点从1开始标号)

输出描述:

一行一个数字,最长的简单路径的长度

输入样例:

3
2
3
2

输出样例:

3

核心思想:

记忆化搜索。
注意存在环。详见代码注释。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+20;
//a数组存图,dp记忆长度,vis表示第几次搜索的
//fa[i]:当点i不在环中是,fa[i]=i;
//在环中时,fa[i]表示环周长的存储位置 
int a[N],dp[N],vis[N],fa[N];
struct node{
	int v,z;//v表示长度,z表示环的全部长度存储的位置 
	node(){}
	node(int vv,int zz)
	{
		v=vv;
		z=zz;
	}
};
node dfs(int x,int ci)//ci表示第几次搜索 
{
	//剪枝 
	if(vis[x]==ci) return node(0,x);//此次搜索构成了一个新环 
	if(vis[x]) return node(dp[fa[x]],-1);//此点被搜过 
	//主函数体 
	vis[x]=ci;//此点在第ci次被搜索 
	node te=dfs(a[x],ci);//继续深搜
	fa[x]=(te.z==-1?x:te.z); //fa[x]赋值 
	dp[x]=te.v+1;//dp[x]赋值 
	//回溯 
	node re;
	re.v=dp[x];
	re.z=(x==te.z?-1:te.z);
	return re;
}
int main()
{
	int n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		ans=max(ans,dfs(i,i).v);
	cout<<ans<<endl;
	return 0;
}
发布了147 篇原创文章 · 获赞 135 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Nothing_but_Fight/article/details/104333184
今日推荐