Tarjan算法

dfs树:对图进行dfs时删除所有未经过的边形成的树

dfs序:对点dfs的顺序

对有向图进行dfs时遇到的边:

~树边:一般边,构成树

~返祖边:指向祖先的边

~横叉边:(从一个叉跳向另一个)指向搜索过的点的边

维护dfs的栈,树根到当前点的节点序列

dfn[u]:u的dfs序

low[u]:u通过树边和至多一条返祖边能访问的dfn的最小值

如果一个点能访问到的最早的点为这个点本身(low=dfn)

就会形成一个新的强连通分量!

 

复制代码
void dfs(int u){
    dfn[u] = low[u] = ++dfs_clock;
    s.push(u);
    /*考虑u能到的所有点v*/{
        if(!dfn[v]) dfs(v) low[u] = min(low[u],low[v]);//树边 
        else if(!sccnum[v]) low[u] = min(low[u],dfn[v]);//返祖边 
        else //横叉边,不管 
    } 
    if(low[u]==dfn[u]){ //产生了新的scc! 
        scccnt++;
        //以下遍历了scc所有点,可以在此记录信息 
        while(1){
            int x = s.top();s.pop();
            sccnum[x] = scccnt;
            sccsz[scccnt]++;
            if(x == u) break;
        }
    }
}
复制代码

 

以下为无向图中概念:

割点:删去这个点,图的联通块个数增加

桥:删去这条边,图的联通块个数增加

点联通度:最小点数使得删去之后图不连通

边联通度:最小边数使得删去之后图不连通

点双:无割点/点联通度>=2/任意2点间存在至少2条点不重复路径

边双:无桥/边联通度>=2/任意2点间存在至少2条边不重复路径

点双边双联通分量:无向图的极大点双/边双联通子图

割点将图分割成若干点双,桥将图分割成若干个边双

桥不属于任何边双,割点属于与其相连的所有点双

 

 

对于边(u,v):

若low[v] > dfn[u]则(u,v)是桥;

若low[v] <= dfn[u] 则u是割点(只有一个儿子的根节点除外);

Tarjan:把图上问题转化为树问题求解。

例:

给你一个有向图,标记其中一点,该点所能到达的点也会被标记,

求至少标记点个数;

求至少加入多少单向边可以使手动标记任意一个点就能标记所有点;

分析:Q1:入度为0的点个数

Q2:加入的单向边需满足(i,j)且点i出度为0,点j入度为0

不断加入,直到消除所有入度为0和出度为0的点就好了

注意:操作中要对每一个入度为0的点,加入一个不能到达它的(有出度为0的点?出度为0的点:任意点)

答案:max(入度为0点个数,出度为0点个数

max(入度为0的点个数,出度为0的点个数)

 

posted @   yinfelix  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示