无向图的连通性bz(双连通)桥

1、啥叫双连通,一个图,不存在割点,桥就是双连通。

 这样的图有啥性质:从x到y一定存在至少两条不共边的路(可以共点)。

 缩点是啥:把各各双连通的块划分成一个,产生一个新图(树,一定不成环)。

2、写法

  1、先用tarjan求出来割边。

  2、dfs给每一块双连通标号。

  3、对于是桥的边,建一个新图,其中newx,newy分别为c[x],c[y]。不是割边的端点不进行操作。

 

  

//求割边
void tarjan(int x,int in_edge)
{
    dfn[x] = low[x] = ++num;
    for(int i = head[x];i;i = nextt[i]){
        int y = ver[i];
        if(!dfn[y]){
            tarjan(y,i);
            low[x] = min(low[x],low[y]);
            if(low[y] > dfn[x])
                bridge[i] = bridge[i^1] = 1;
             //que.push(make_pair(min(i,i^1),max(i,i^1)));
        }
        else if(i!=(in_edge^1)) 
            low[x] = min(low[x],dfn[y]);
    }
}
//给每一块标号
int c[maxn],dcc;
void dfs(int x)
{
    c[x] = dcc;
    for(int i = head[x];i;i = nextt[i]){
        int y = ver[i];
        if(c[y] || bridge[i]) continue;
        dfs(y);
    }
}
//main main
tot = 1;
for(int i = 1;i <= m;++i){
    int x,y;
    cin>>x>>y;
    add(x,y);add(y,x);
}
for(int i = 1;i <= n;++i){
    if(!dfn[i]) tarjan(i,0);
}

for(int i = 1;i <= n;++i){
    if(!c[i]){
        ++dcc;
        dfs(i);
    }
}
totc = 0;
for(int i = 2; i <= tot;i = i+2){
    int x = ver[i],y = ver[i^1];
    if(c[x] == c[y]) continue;
    //cout<<c[x]<<sp<<c[y]<<endl;
    addc(c[y],c[x]);
    addc(c[x],c[y]);
}

 

posted @ 2020-08-21 20:26  阿斯水生产线  阅读(206)  评论(0)    收藏  举报