hdu1269 迷宫城堡,有向图的强连通分量 , Tarjan算法

hdu1269 迷宫城堡

验证给出的有向图是不是强连通图。。。

Tarjan算法板子题

Tarjan算法的基础是DFS,对于每个节点、每条边都搜索一次,时间复杂度为O(V+E)。

算法步骤:

1、搜索到某一个点时,将该点的Low值标上时间戳,然后将自己作为所在强连通分量的根节点(就是赋值Dfn=Low=time)

2、将该点压入栈。

3、当点p有与点p’相连时,如果此时p’不在栈中,p的low值为两点的low值中较小的一个。

4、当点p有与点p’相连时,如果此时p’在栈中,p的low值为p的low值和p’的dfn值中较小的一个。

注释:因为此时在栈中,所以p‘的强连通分量的父节点需要重新指向(感觉学过并查集理解得更快一些) 。

5、当子树全部遍历完毕,将low值等于dfn值,则将它以及在它之上的元素弹出栈。这些出栈的元素组成一个强连通分量。

   这里的子树全部遍历完毕不是指的所有子节点遍历完毕,而是一个强连通分量的搜索树遍历完毕。

6、选择一个未搜索的节点作为根节点进行搜索,直到所有节点搜索完毕为止。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<stack>
using namespace std;

const int maxn = 100000 + 10;

vector<int> G[maxn];
int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
stack<int> S;

void dfs(int u){
    pre[u] = lowlink[u] = ++ dfs_clock;
    S.push(u);
    for(int i=0; i<G[u].size(); ++i){
        int v = G[u][i];
        if(!pre[v]){
            dfs(v);
            lowlink[u] = min(lowlink[u], lowlink[v]);
        }else if(!sccno[v]){
            lowlink[u] = min(lowlink[u], pre[v]);
        }
    }
    if(lowlink[u] == pre[u]){
        scc_cnt++;
        for(;;){
            int x = S.top(); S.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}

void find_scc(int n){
    dfs_clock = scc_cnt = 0;
    memset(sccno, 0, sizeof sccno);
    memset(pre, 0, sizeof pre );
    for(int i=0; i<n; ++i)
        if(!pre[i]) dfs(i);
}

int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        if(n==0 && m==0) break;
        for(int i=0; i<n; ++i) G[i].clear();
        for(int i=0; i<m; ++i)
        {
            int u, v;
            scanf("%d%d", &u, &v); u--; v--;
            G[u].push_back(v);
        }

        find_scc(n);

        if(scc_cnt == 1) puts("Yes");  //强连通分量只有一个则说明原图就是强连通图。
        else puts("No");
    }
}

hdu1269 迷宫城堡,有向图的强连通分量 , Tarjan算法,布布扣,bubuko.com

时间: 2024-10-20 22:48:26

hdu1269 迷宫城堡,有向图的强连通分量 , Tarjan算法的相关文章

HDU 1269 强连通分量tarjan算法

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6655    Accepted Submission(s): 2973 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房

图之强连通、强连通图、强连通分量 Tarjan算法

强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components,SCC)的定义是:极大的强连通子图. 这里想要介绍的是如何来求强连通分量. Tarjan 算法 Robert E. Tarjan (1948~) 美国人. Tarjan 发明了很多算法结构.光 Tarjan 算法就有很多,比如求各种联通分量的 Tarjan 算法,求 LCA(Lowest Comm

求有向图的强连通分量的算法

下面是求有向图的强连通分量的算法的代码: import java.util.Scanner; class Qiufenliang//定义求强连通分量的类 { String lu="";//定义的一个字符型变量,记录强连通分量的路径 public static int s=0; public void qiu(int a[][],int l)//定义函数,参数a为二维数组,参数l为数组的维数 { int t=0;//定义int型变量,进行数量的统计 for(int i=1;i<l;

HDU ACM 1269迷宫城堡-&gt;有向强连通分量(tarjan算法实践)

分析:本题判断一个图是否是有向强连通分量,这里使用tarjan算法求解. #include<iostream> #include<vector> #include<stack> using namespace std; vector<int> map[10002]; stack<int> tarjan_stack; int low[10002]; int dfn[10002]; bool vis[10002]; int cnt,pos; void

图论-强连通分量-Tarjan算法

有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在百科上和别的大神的博客中不太一样,暂且采用百科上的定义) Tarjan算法的功能就是求有向图中的强连通分量 思路: 定义DFNi存放访问到i结点的次序(时间戳),Lowi存放i结点及向i下方深搜到的结点中能追溯到的访问次序最小的结点的访问次序(即这些结点回溯上去能找到的最小的DFN值),找到未被访问

求图的强连通分量--tarjan算法

一:tarjan算法详解 ?思想: ? ?做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间.(也就是之后的深搜所能到达的最小开始时间)初始时dfn[i]=low[i] ? ?在DFS过程中会形成一搜索树.在搜索树上越先遍历到的节点,显然dfn的值就越小. ? ?DFS过程中,碰到哪个节点,就将哪个节点入栈.栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈. ?

poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27496   Accepted: 11059 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows

强连通分量--tarjan算法

今天学了一个强连通分量,用tarjan做.北京之前讲过,今天讲完和之前一样,没有什么进步.上课没听讲,只好回来搞,这里安利一个博客:链接 https://blog.csdn.net/qq_34374664/article/details/77488976 讲一下我自己的体会吧,其实就是维护一个栈,然后树上跑dfs,每个节点存两个值:dn和low,dn代表dfs的顺序(时间),low代表的是他可以连通的最小的节点. 模拟一下,然后就会发现,其实整个算法就是模拟了一下将每个点压入栈.然后遇到之前在栈

求强连通分量Tarjan算法

int dfn[16]; // 时间戳 int dfn_num = 0; // 时间 int low[16]; // 节点u所能访问到的最小时间戳 int inSt[16]; // 节点u是否在栈中. int st[16]; int top = 0; // 我们维护的信息. int col[16]; // 给节点染色, 同一个连通块的节点应该是同一个颜色的. int col_num = 0; // 颜色值. int size[16]; // 每个颜色值所拥有的块数. /* 第一步: 访问当前节点

强连通分量Tarjan算法模板

#include<map> #include<set> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<iomanip> #include<sstream> #include