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

https://ac.nowcoder.com/acm/contest/3007/B

 

此题我不但又双叒叕做麻烦了,而且达到了我麻烦的巅峰

tarjan重构图然后新图上拓扑dp

吐血。。。

 

因为他是n个点n条边,且每个点只有一条出边

所以该图是一个基环内向树

从一个点出发,要么走到链的一段,要么停在一个环上

只需要记忆化dfs找出那个环即可

注意可能有自环

稍稍借鉴了一下tarja的思路

 

#include
#include
 
using namespace std;

#define N 1000001
 
int to[N],f[N]; 
bool vis[N];

int dfn[N],tim;

int sum,tag;

void dfs(int x)
{
    vis[x]=true;
    dfn[x]=++tim;
    if(!dfn[to[x]]) 
    {
        dfs(to[x]);
        if(tag) 
        {
            f[x]=sum;
            if(tag==x) tag=0;
        }
        else f[x]=f[to[x]]+1;
    }
    else if(vis[to[x]]) 
    {
        sum=dfn[x]-dfn[to[x]]+1;
        f[x]=sum;
        tag=to[x];
        if(x==tag) tag=0;
    }
    else f[x]=f[to[x]]+1;
    vis[x]=false;
}

int main()
{
     int n;
     scanf("%d",&n);
     for(int i=1;i<=n;++i) scanf("%d",&to[i]);
     for(int i=1;i<=n;++i) 
         if(!dfn[i]) dfs(i);
     int ans=0;
     for(int i=1;i<=n;++i) ans=max(ans,f[i]);
     printf("%d",ans);
}

 

你可能感兴趣的:(2020牛客寒假算法基础集训营6 B 图)