2020牛客寒假算法基础集训营6 B题

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

输入描述:

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

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


这道题就是先拓扑排序求出各个点的(其实就是支链)最长长度,然后拓扑没有遍历到的点也就是环上的点,找出这些点在遍历一遍,找出环上的点能连接的最长长度和环的大小,
为啥要遍历所有没有遍历的点,因为这题的图可以是不连通的,也就是说可以有多个环;

代码:

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
#define inf 0x3f3f3f3f
//ios::sync_with_stdio(false);
using namespace std;
const int N=1000100;
const int M=1000100;
const ll mod=998244353;
int in[N];
int n;
struct Node{
	int to,nex;
}edge[N*2];
int head[N];
int cnt;
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].nex=head[p];
	head[p]=cnt++;
}
int dp[N];
queue<int>qu;
bool vis[N];
void bfs(){
	while(!qu.empty()){
		int u=qu.front();
		vis[u]=true;
		qu.pop();
		for(int i=head[u];~i;i=edge[i].nex){
			int v=edge[i].to;
			dp[v]=max(dp[v],dp[u]+1);
			in[v]--;
			if(in[v]==0) qu.push(v);
		}
	}
}
int sum,mmax;
bool f[N];
void dfs(int p){
	f[p]=true;
	mmax=max(mmax,dp[p]);//最长支链大小
	sum++;//环的大小 
	for(int i=head[p];~i;i=edge[i].nex){
		int u=edge[i].to;
		if(!f[u]) dfs(u);
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++){
		int q;
		cin>>q;
		add(i,q);
		in[q]++;//入度
	}
	for(int i=1;i<=n;i++){
		dp[i]=1;
		if(in[i]==0) qu.push(i);
	}
	bfs();
	int ans=0;
	for(int i=1;i<=n;i++){
		if(!vis[i]&&!f[i]){
			sum=mmax=0;
			dfs(i);
			ans=max(ans,sum+mmax-1);
		}
	}
	cout<<ans<<endl;
	return 0;
}
发布了203 篇原创文章 · 获赞 45 · 访问量 7852

猜你喜欢

转载自blog.csdn.net/qq_44291254/article/details/104345509