图论算法-Tarjan模板 【缩点;割顶;双连通分量】


为小伙伴们总结的Tarjan三大算法


Tarjan缩点(求强连通分量)

int n;
int low[100010],dfn[100010];
bool ins[100010];
int col[100010];//记录每个点所属强连通分量(即染色)
vector<int> map[100010];
stack<int> st;
int tot;//时间戳
int colnum;//记录强连通分量个数

void tarjan(int u)
{
    low[u]=dfn[u]=++tot;
    st.push(u);
    ins[u]=true;

    for(int j=0;j<map[u].size();j++)
    {
        int v=map[u][j];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }

        else if(ins[v])
        low[u]=min(low[u],dfn[v]);
    }

    if(low[u]==dfn[u])
    {
        //到这里即发现了一个新的强连通分量
        colnum++;

        int temp;
        int cont=0;
        do
        {
            temp=st.top();
            st.pop();
            ins[temp]=false;

            //将同一强连通分量的点染色,表示一个缩点
            col[temp]=colnum;

            //在这里也可以对该强连通分量进行一些其他操作
            //例如保存该缩点所包含的原节点
        }
        while(temp!=u);
    }
}

void init()
{
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(col,0,sizeof(col));
    memset(ins,false,sizeof(ins));
    tot=colnum=0;
}

void solve()
{
    init();
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        tarjan(i);
    }
}

Tarjan求割点(割顶)

int n;
vector<int> map[100010];
int low[100010],dfn[100010];
bool cut[1000010];//记录割点
int tot;

void tarjan(int u,int fa)
{
    low[u]=dfn[u]=++tot;
    int child=0;
    for(int j=0;j<map[u].size();j++)
    {
        int v=map[u][j];
        if(!dfn[v])
        {
            child++;
            tarjan(v,u);
            low[u]=min(low[u],low[v]);

            if(low[v]>=dfn[u])
            cut[u]=true;
        }

        else if(dfn[v]<dfn[u]&&v!=fa)
        low[u]=min(low[u],dfn[v]);
    }

    if(fa<0&&child==1)
    cut[u]=false;
}

void init()
{
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(cut,false,sizeof(cut));
    tot=0;
}

void solve()
{

    init();
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        tarjan(i,-1);
        //**高亮**这里的第二个参数一定要设为负数
    }
    //cut[i]==true即表示i为割点
}

Tarjan求点-双连通分量

int n;
vector<int> map[100010];
int low[100010],dfn[100010];
bool cut[1000010];
int bcc[1000010];
int tot;
int bcc_cont//记录双连通分量个数;
struct edge{int u,v};
stack<edge> E;

void tarjan(int u,int fa)
{
    low[u]=dfn[u]=++tot;
    int child=0;
    for(int j=0;j<map[u].size();j++)
    {
        int v=map[u][j];
        edge e=(edge) {u,v};

        if(!dfn[v])
        {
            E.push(e);
            child++;
            tarjan(v,u);
            low[u]=min(low[u],low[v]);

            if(low[v]>=dfn[u])
            {
                //到这里即发现了一个新的双连通分量
                cut[u]=true;
                bcc_cont++:

                while(1)
                {
                    edge temp=E.top();
                    E.pop();

                    if(bccno[temp.u]!=bcc_cont)
                    bccno[temp.u]=bcc_cont;
                    if(bccno[temp.v]!=bcc_cont)
                    bccno[temp.v]=bcc_cont;

                    if(temp.u==u&&temp.v==v)
                    break;
                }
            }
        }

        else if(dfn[v]<dfn[u]&&v!=fa)
        {
            E.push(e);
            low[u]=min(low[u],dfn[v]);
        }
    }

    if(fa<0&&child==1)
    cut[u]=false;
}

void init()
{
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(bccno,0,sizeof(bccno));
    tot=bcc_cont=0;
}

void solve()
{

    init();
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        tarjan(i,-1);//**高亮**这里的第二个参数一定要设为负数
    }
}

其实三个算法思路都基本一致

毕竟都是同一个人提出的嘛

图论算法-Tarjan模板 【缩点;割顶;双连通分量】的更多相关文章

  1. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  2. tarjan算法求无向图的桥、边双连通分量并缩点

    // tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...

  3. Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】

    一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...

  4. (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)

    基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...

  5. tarjan求桥、割顶

    若low[v]>dfn[u],则(u,v)为割边.但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理.我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父 ...

  6. 图论--割边--Tarjan模板

    #include<iostream> #include<stdio.h> #include<vector> using namespace std; const i ...

  7. 图论--割点--Tarjan模板

    #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> ...

  8. [Tarjan系列] Tarjan算法求无向图的双连通分量

    这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...

  9. 点/边 双连通分量---Tarjan算法

    运用Tarjan算法,求解图的点/边双连通分量. 1.点双连通分量[块] 割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义. typedef struct{ //栈结点结构 保 ...

随机推荐

  1. 织梦dedecmsV5.7联动类型无法显示的处理方法

    最近织梦dedecms在新的功能中添加了一个联动类型这样的一个功能.所谓的联动类型,类似于一级目录下有二级目录,二级目录下又有三级目录,可以理解为数据结构中树形结构.级和级之间都是有着联系的.为了让大 ...

  2. vue-cli的webpack模版项目配置解析

    上一篇文章已经分析了build/dev-server.js,里面使用到了其他config文件. 那么我们这篇文章,按着dev-server.js的使用顺序,来分析下其他文件. 首选,调用check-v ...

  3. SpringMVC图片上传与显示

    @RestController @Scope("prototype") @RequestMapping("/xxxx/xxx/main") public cla ...

  4. 开地址哈希表(Hash Table)的接口定义与实现分析

    开地址哈希函数的接口定义 基本的操作包括:初始化开地址哈希表.销毁开地址哈希表.插入元素.删除元素.查找元素.获取元素个数. 各种操作的定义如下: ohtbl_init int ohtbl_init ...

  5. 寄存器(CPU原理)

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  6. 基于BCGP库的界面效果

  7. alwaysOn中关于维护计划的应用方案

    由于alwaysOn环境下主副本所在的实际服务器不固定, 所以我目前采取的方案是创建维护计划的时候, 在各个服务器上创建一份维护计划. (假设有2个服务器需要故障转移, 那么就在这两个服务器上分别创建 ...

  8. Execption:the database returned no natively generated identity value

    org.hibernate.HibernateException: The database returned no natively generated identity value at org. ...

  9. css 对图片颜色的处理

    很久很久以前,在一个项目中,经理要求对一个图片做模糊处理.第一反应是这个要找 ui 给个模糊图片.可当时 ui 不在呀,项目又着急,只能自己搞.我一个前端,ps 技术实在不咋的,叫我切切图还可以,叫我 ...

  10. DirectX SDK (June 2010)安装错误S1023的一个解决方法

    在安装DXSDK_Jun10.exe时一个常见的安装失败的代号是S1023,一般出现这种错误的原因是系统中已经安装了Visual Studio 2010及以上的版本. 在[控制面板]中找到这两个: 如 ...