zoukankan      html  css  js  c++  java
  • 图(基环树)

    链接: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

    官方题解:

    这是一个简单的有关基环树的问题。
    可以证明,每个点出度都为1的有向图是一个基环内向树森林。
    关于这一部分的内容,可以自行查阅资料。
    这里我们要用到的结论是:从一个点出发,沿着出边一路走下去,一定会走到一个环。
    所以我们选择dfs,当遍历到一个已在dfs栈中的节点时,就说明找到了环,可以结束统计。
    但这样是会超时的,于是我们选择带“记忆化”的dfs,从一个点开始沿着出边走下去,每当走到一个在之前某次dfs中经过的点时,就可以利用上一次的答案完成求解。
    实现上有一些细节,要注意不要让复杂度退化。
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <sstream>
    13 const int INF=0x3f3f3f3f;
    14 typedef long long LL;
    15 const double eps =1e-8;
    16 const int mod=1e9+7;
    17 const int maxn=1e6+10;
    18 using namespace std;
    19 
    20 int to[maxn];
    21 int dis[maxn];
    22 int vis[maxn];
    23 
    24 int DFS(int u)
    25 {
    26     vis[u]=1;//入栈 
    27     if(dis[u])//已经计算过 
    28     {
    29         vis[u]=0;//出栈 
    30         return dis[u];
    31     }
    32     if(to[u]==0)//该点没有出边,好像没什么用 
    33     {
    34         vis[u]=0;
    35         return dis[u]=1;
    36     }
    37     if(vis[to[u]])//遇到环 
    38     {
    39         int rt=to[u];//环开始的地方 
    40         int v=to[rt];
    41         int cnt=1;//计数 
    42         while(v!=rt)//数一下这个环有几个点 
    43         {
    44             cnt++;
    45             v=to[v];
    46         }
    47         dis[rt]=cnt;
    48         v=to[rt];
    49         while(v!=rt)//更新该环内所有的dis 
    50         {
    51             dis[v]=cnt;
    52             v=to[v];
    53         }
    54         vis[u]=0;
    55         return dis[u];
    56     }
    57     int res=DFS(to[u])+1;//递归; 
    58     vis[u]=0;//出栈 
    59     if(dis[u]) return dis[u];//环内计算过了,记忆化搜索 
    60     else return dis[u]=res;//否则正常
    61 }
    62 
    63 int main()
    64 {
    65     #ifdef DEBUG
    66     freopen("sample.txt","r",stdin);
    67     #endif
    68     
    69     int n,m; 
    70     scanf("%d",&n);
    71     for(int i=1;i<=n;i++)
    72         scanf("%d",&to[i]);
    73     int ans=0;
    74     for(int i=1;i<=n;i++)
    75     {
    76         if(!dis[i]) DFS(i);
    77         ans=max(ans,dis[i]);//求出图中最长的简单路径包含点的数量
    78     }
    79     printf("%d
    ",ans);
    80     
    81     return 0;
    82 }

    -

  • 相关阅读:
    【结构型】Proxy模式
    【结构型】Flyweight模式
    【结构型】Facade模式
    【结构型】Decorate模式
    【结构型】Composite模式
    适配器模式 -- 大话设计模式
    状态模式 -- 大话设计模式
    抽象工厂模式 -- 大话设计模式
    建造者模式 -- 大话设计模式
    观察者模式 -- 大话设计模式
  • 原文地址:https://www.cnblogs.com/jiamian/p/12319262.html
Copyright © 2011-2022 走看看