2020牛客算法寒假基础训练营6——B-图

题目描述
现在有一个N个点的有向图,每个点仅有一条出边
你需要求出图中最长的简单路径包含点的数量
(1≤N≤1,000,000)
输入描述:
第一行一个数字N
接下来N行,每行一个正整数,第i+1行的数字表示第i个点出边终点的编号
(点从1开始标号)
输出描述:
一行一个数字,最长的简单路径的长度
示例1
输入
复制
3
2
3
2
输出
复制
3

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 1000005;
int n;
int a[maxn],cnt[maxn],vis[maxn],dfn[maxn],sta[maxn];
int dfs(int x){
    // 记忆化搜索
    // 如果有记录的话,直接返回
    // 否则,层层下去
    if(cnt[x]) return cnt[x]; 
    return cnt[x] = 1+dfs(a[x]);/*每一个不在环内的数,都可以递归下去,
	在环内的数有长度记录,因为每一个数都肯定会递归到一个环然后结束,所以可以得出每个数的最长长度; 
}
int main(void){
    int i,j,k,h;
    cin>>n;
    for(i = 1;i<=n;++i) cin>>a[i];
    for(i = 1;i<=n;++i){
        if(!vis[i]){
            j = i;
            while(vis[j] == 0){ //此点未被访问过,记录,一直跑下去
                sta[++sta[0]] = j;/*此处记录是为了方便后面的dfn[]数组清零*/ 
                vis[j] = dfn[j] = 1;/*dfn[]用来记录是否继续下去可以成环; */ 
                j = a[j];
            }
            if(dfn[j]){  // 此点访问过,说明形成一个环,计算环的长度以及将环内都赋予同一个值
                k = j,h = 0;
                do{
                    k = a[k];
                    ++h;
                }while(k != j); // 计算环长度
                do{
                    k = a[k];
                    cnt[k] = h;
                }while( k != j); // 将环内所有点赋予同一个长度
            }
            while(sta[0]){ /*将判断环的数组还原,因为如果不清零,
			会直接影响到下
			一次是否成环的判断*/ 
                dfn[sta[sta[0]]] = 0;
                --sta[0];
            }
        }  
    }
    int ans = 0;
    for(int i = 1;i<=n;++i){
        ans = max(ans,dfs(i));
    }
    cout<<ans<<endl;
    return 0;
}

理解得还是不太好,第一次接触图,wtcl;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值