zoukankan      html  css  js  c++  java
  • HDU 1269 迷宫城堡 【强联通分量(模版题)】

    知识讲解:
    在代码里我们是围绕 low 和 dfn 来进行DFS,所以我们务必明白 low 和 dfn 是干什么的? 有什么用,这样才能掌握他。
     
    1.  dfn[]  遍历到这个点的时间
    2.  low[]  遍历到这个所能连接到的最短时间,说明那个最短时间可以遍历带他,他也可以走到那个最短时间。
    3.  我们每次出栈的点就是一个强联通分量(这里建议观看一下课件里面的Tarjan求强联通算法的模拟过程)。
     
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    #define maxn 10005
    int dfn[maxn];///代表最先遍历到这个点的时间
    int low[maxn];///这个点所能到达之前最早的时间点
    int Stack[maxn];///自定义的栈,比较好用
    int cnt, bloks;///cnt总的连通个数, 连通块的总个数 
    bool InStack[maxn];///判断这个点是否在栈中
    int n, m, Time, top;///Time 时间点,  top用于栈操作
    vector<vector<int> > G;
    void Tarjan(int u)
    {
        low[u] = dfn[u] = ++Time;///更新时间点
        Stack[top++] = u;///将u压入栈中
        InStack[u] = true;
        int len = G[u].size(), v;///深度优先遍历与u相连的所有节点
        
        for(int i=0; i<len; i++)
        {
            v = G[u][i];
    
            if(!dfn[v])///我们可以用dfn判断这个点是否曾经被遍历过
            {///若是没被遍历过,那么我们就遍历一下
                Tarjan(v);
                ///假如u点下方节点v可以到达的点那么u点也一定能到达
                low[u] = min(low[u], low[v]);
                ///在两者中取一个最小的,到达点
            }
            else if( InStack[v] )
            /**如果遍历的这个点已经在栈中了,那么就需要更新一下,这里其实写成low[u] = min(low[u],low[v])也可以肯定是没错的,但是
            在我们求割点的时候就必须要写成low[u] = min(low[u], dfn[v]),到求割点的时候我们会好好解释一下*/
                low[u] = min(low[u], dfn[v]);
        }
        /**当这个节点的所有节点已经遍历完了并且 low[u] == dfn[u],这个时候说明我们已经返回到了这个点的最初的时间点的位置
            将我们栈中的所有元素出栈就可以完成连通图求解了*/
        if(low[u] == dfn[u])
        {
            do
            {
                cnt ++;
                v = Stack[--top];
                InStack[v] = false;
            }while(u != v);
            bloks ++;
        }
    }
    void Init()
    {
        G.clear();
        G.resize(n+1);
        memset(low, 0, sizeof(low));
        memset(dfn, 0, sizeof(dfn));
        memset(Stack, 0, sizeof(Stack));
        memset(InStack, false, sizeof(InStack));
        bloks = cnt = Time = top = 0;
    }
    
    int main()
    {
        while(scanf("%d %d",&n, &m), n+m)
        {
            Init();
            while(m --)
            {
                int a, b;
                scanf("%d %d", &a, &b);
                G[a].push_back(b);
            }
            Tarjan(1);
            if( cnt == n && bloks == 1 )
                puts("Yes");
            else
                puts("No");
        }
        return 0;
    }
  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/chenchengxun/p/4718698.html
Copyright © 2011-2022 走看看