zoukankan      html  css  js  c++  java
  • Tarjan专题总结复习

    定义:

    (dfn[x])(x)第一次被访问的时间顺序(时间戳)

    搜索树:每个节点只访问一次,所有访问过的边((x,y))构成一棵搜索树

    (low[x]):定义为以下节点的时间戳的最小值:

    (1.)(subtree(x))中的节点。

    (2.)通过(1)不在搜索树上的边,能够到达(subtree(x))的节点。

    代码:

    void Tarjan(int x)
    {
        low[x] = dfn[x] = ++ ind;//初始值
        que[ ++ top] = x;//进队
        vis[x] = 1;//标记
    	for (int i = hd[x]; i; i = nxt[i])
    	{
    		int y = to[i];//枚举x子节点y
    		if (!dfn[y])
    		{
    			Tarjan(y);
    			low[x] = min(low[x], low[y]);//在子树中,是x的儿子,直接更新
    		}
    		else if (vis[y]) low[x] = min(low[x], dfn[y]);
            //已经访问过,且y不是x的儿子,因为dfn[y]一定小于dfn[x],那么用dfn[y]更新(不用low[y]更新,因为它们不一定在同一个强连通分量中,防止更新过头)
        }
        if (dfn[x] == low[x])//形成了一个环,说明x是一个强连通分量的根
        {
            cnt ++ ;//新的强连通分量
            int now = -1;
            do
            {
                now = que[top -- ];
                vis[now] = 0;
                col[now] = cnt;//染色,标记now属于当前强连通分量cnt
            } while (now != x);//弹出
        }
        return;
    }
    

    应用

    缩点

    在跑了一遍Tarjan后,对于原来的每条边对应的点对((x,y)),若(col[x]==col[y]),说明它们在同一个强连通分量内,则它们不用在新的图中连边,否则要连。

    伪代码:

    for (int x = 1; x <= n; ++ x)
    {
        for (int i = hd[x]; i; i = nxt[i])
        {
            int y = to[i];
            if (col[x] != col[y]) add(col[x], col[y]);
        }
    }
    

    割点/割边

    割点定义:若去掉无向联通图的某个点后,此图不连通,则该点为割点。割边同理。

    判断方法:

    割边:(dfn[x]<low[y])(说明从(subtree(y))出发,在不经过(x,y)的前提下,无论走那条边,都无法到达(x)或比(x)更早的节点,这就是一条割边)

    割点:(dfn[x]le{low[y]})(和割边同理。特别地,若(x)是搜索树根节点,那么(x)是割点当且仅当它存在至少两个子节点(y_1,y_2)满足条件)

    伪代码(割点)

    if (low[y] >= dfn[x])
    {
        t ++ ;		
        if (x != rt || t > 1) cut[x] = 1;	
    }
    
  • 相关阅读:
    C#读物
    那些健康手环真的值得买么?
    书籍推荐系列之一 -- 《凤凰项目:一个IT运维的传奇故事》
    测试
    HDU-2024 C语言合法标识符
    HDU-4548 美素数
    求最大流dinic算法模板
    最小费用最大流模板理解
    网络流初步——增广路代码的分析
    最短路的另外两种算法
  • 原文地址:https://www.cnblogs.com/andysj/p/13913933.html
Copyright © 2011-2022 走看看