tajan的dfs树系列算法:

求解割点,桥,强连通分量,点双联通分量,边双联通分量;

tajan是一个dfs,把一个图变成一个dfs树结构,

dfs树结构,本质是通过一个没有任何要求的dfs把图的边分为:树边和返祖边:

  • 树边:dfs中父节点与其未曾遍历过的子节点间的边,
  • 返祖边:父节点与他的dfs中曾作为该父节点祖先的子节点间的边

在有向图中,除了这二种边外,还有父节点与曾遍历过的子节点间的边,然而这个子节点不是父节点的祖先,

然而这种边在tarjan中没有意义,我们所求的东西用不上她们

伪代码:

深搜(点now){

  更新点now——

    dfs序(dfn)与目前可到dfn最小祖先的dfn(low),标记已经遍历(vis),确认now将是他后继递归的点的祖先(instk),其他

  for(以now为起点的所有边)

    if(边终点to未遍历)

      深搜(to),low[now]=min(low[now],low[to])

    else

      if(instk[to]为真)//无向图可以不存在这个

        low[now]=min(low[now],dfn[to])

  更新instk[now]为假

}

求(无向图)割点,桥:

割点:无向图中,删除之可改变图的连通性的点

  两种:

  • 两个点双连通分量的公共点
  • 两个点双连通分量直接存在一条边连接,这条边的两端点

桥:无向图中,删除之可改变图的连通性的边

  一种:

  两个边双连通分量间的连边;

求法:

割点:这个点儿子中有至少一个的low小于这个点的dfn

桥:该边终点的low=dfn

例题:

hihocoder1183连通性一·割边与割点

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
struct ss{
    int to,next;
}e[200010];
struct Cl{
    int u,v;
}Cedge[200010];
int first[20010],num;
int pnu,enu;
int Cpoint[20010];
int dfn[20010],low[20010],vis[20010];
bool cmp(Cl a,Cl b){
    return a.u<b.u||(a.u==b.u&&a.v<b.v);
}
void Input();
void work();
void Output();
void build(int ,int );
void Init();
void dfs_1(int ,int );
void dfs_2(int ,int );
int main()
{
    Input();
    work();
    Output();
    return 0;
}
void Input(){
    int i,j,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++){
        scanf("%d%d",&j,&k);
        build(j,k);build(k,j);
    }
}
void work(){
    pnu=0;enu=0;
    Init();
    dfs_1(1,0);
    Init();
    dfs_2(1,0);
}
void Output(){
    int i;
    for(i=1;i<=enu;i++)
        if(Cedge[i].u>Cedge[i].v)
            swap(Cedge[i].u,Cedge[i].v);
    sort(Cpoint+1,Cpoint+pnu+1);
    sort(Cedge+1,Cedge+enu+1,cmp);
    for(i=1;i<=pnu;i++)
        printf("%d ",Cpoint[i]);
    if(pnu==0)
        printf("Null");
    printf("\n");
    for(i=1;i<=enu;i++)
        printf("%d %d\n",Cedge[i].u,Cedge[i].v);
}
void build(int f,int t){
    e[++num].next=first[f];
    e[num].to=t;
    first[f]=num;
}
void Init(){
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(vis,0,sizeof(vis));
    num=0;
}
void dfs_1(int now,int fa){
    int i,p=0;
    if(now!=1)p=1;
    dfn[now]=low[now]=++num;vis[now]=1;
    for(i=first[now];i;i=e[i].next)
        if(e[i].to!=fa){
            if(!vis[e[i].to]){
                dfs_1(e[i].to,now);
                if(low[e[i].to]>=dfn[now])p++;
                if(low[now]>low[e[i].to])
                    low[now]=low[e[i].to];
            }
            else
                if(low[now]>dfn[e[i].to])
                    low[now]=dfn[e[i].to];
        }
    if(p>=2)
        Cpoint[++pnu]=now;
}
void dfs_2(int now,int fa){
    int i;
    dfn[now]=low[now]=++num;vis[now]=1;
    for(i=first[now];i;i=e[i].next)
        if(e[i].to!=fa){
            if(!vis[e[i].to]){
                dfs_2(e[i].to,now);
                if(low[now]>low[e[i].to])
                    low[now]=low[e[i].to];
                if(low[e[i].to]>dfn[now])
                    Cedge[++enu].u=now,Cedge[enu].v=e[i].to;
            }
            else
                if(low[now]>dfn[e[i].to])
                    low[now]=dfn[e[i].to];
        }
}
View Code

相关文章:

  • 2021-10-05
  • 2022-12-23
  • 2022-12-23
  • 2021-11-18
  • 2021-07-02
  • 2021-07-05
  • 2021-11-02
  • 2021-08-29
猜你喜欢
  • 2022-01-10
  • 2021-08-05
  • 2021-11-16
  • 2021-12-04
  • 2021-12-15
  • 2021-06-30
  • 2021-11-07
相关资源
相似解决方案