牛客寒假6-B图| 统计环中结点个数,计算最大链长

思路

每个点出度都为1的有向图是一个基环内向树森林。
要用到的结论是:从一个点出发,沿着出边一路走下去,一定会走到一个环。

思路-两个步骤:
遍历起点,dfs时存储以这个点为起点的路径长度,遇到环要把环上所有点的值赋值成相同值
1.统计环个数, 把各个结点值赋值为所在环的结点数量
2.统计各个点到环的距离,更新最大值,最大链长就是环里的结点个数 + 起点点到环的距离

题目地址:https://ac.nowcoder.com/acm/contest/3007/B
参考题解:https://blog.csdn.net/weixin_45766122/article/details/104332347

看图理解更清晰。

AC代码

#include<bits/stdc++.h>
#define ll long long
#define maxn 1000005
using namespace std;

int n,ans,h[maxn],child[maxn];
int vis[maxn];

//基环内向树森林: 从一个点出发,沿着出边一路走下去,一定会走到一个环。 

/*
两个步骤:
	1.统计环个数, 把各个结点值赋值为所在环的结点数量 
	2.统计各个点到环的距离,更新最大值
*/ 
void dfs(int id){
	//1. 暴力统计环 h[child] = 0 说明从有人到达了'我'儿子, 我也能到达我儿子,说明有环了 
    //注: h[child[id] = 0 是一个重要的特征 这时环的起点找到了 就是id->child[id]这条边形成了环 
	if(h[child[id]]==0){ 
        int res = 1;
        int k = child[id];
        while(k != id){ //遇到环 记录环中结点个数 
            res++;
            k=child[k];
        }
        h[k]=res;
        vis[k]=1;
        k=child[k];
        while(k!=id){ //把环上所有点赋值为环中结点的个数  作为他们共同的高度 
            h[k]=res;
            vis[k]=1;
            k=child[k];
        }
        return ;
    }
    
    //2. 下面就是 统计当前点到环的距离 再加上环中结点个数(已经算成结点个数作为距离存储到h数组中了) 
    h[id]=0; //高度设置成0 
    if(vis[child[id]]==0){ //孩子没有去过 
        dfs(child[id]); //去孩子那里玩玩 
        //vis[id] = 0 说明 dfs孩子的过程没有标记我id, 说明我不在儿子形成的环里
        if(vis[id]==0){
            h[id]=h[child[id]]+1; //按正常的dp思想+1距离就行  
            vis[id]=1;
        }
        //else 我和child共同在环中 权值h已经统计成环中结点的数量了 
    }
    else if(vis[child[id]]=1){ //要是孩子被别人去过了 
        h[id]=h[child[id]]+1; //孩子肯定是有值的 赋值为 "孩子到别人的距离再+1"的距离,这里的1是指我到孩子的距离, 
        vis[id] = 1; //标记访问过 
		return ;
    }
    
    return;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&child[i]); //输入孩子 存储图 
    }
    for(int i=1;i<=n;i++) h[i]=-1; //初始化高度 
    ans=0;
    for(int i=1;i<=n;i++){ //遍历起点 
        if(vis[i]==0) dfs(i); //dfs没有标记的点 
        ans=max(ans,h[i]);
    }
    printf("%d",ans);
    return 0;
}
/*
5
2 3 2 3 4
*/ 
posted @ 2020-02-16 11:45  fishers  阅读(301)  评论(0编辑  收藏  举报