牛客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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章