割点和桥

割点和桥
割点:无向图中,如果删除某个点以及和它相邻的所有边之后,图中连通分量数增加,则称该点为割点

桥:无向图中,如果删除某条边之后,图中连通分量数增加,则称该边为桥
tarjan算法计算割点和桥
割点:
1.如果节点\(u\)不是根,则当存在一个以\(u\)为根的子树中的节点\(v\),有\(low[v]>=dfn[u]\)时,说明去掉\(u\)之后会使得\(v\)\(u\)的祖先节点不连通,\(u\)为割点
2.如果节点\(u\)是根,则当根有多于一棵子树时,根为割点

const int maxn=100010;
int dfn[maxn],low[maxn],cut[maxn],dfscnt;

void tarjan(int u,int fa){
    int child=0;
    dfn[u]=low[u]=++dfscnt;
    for(int i=head[u];~i;i=nxt[i]){
        int v=to[i];
        if(!dfn[v]){
            child++;
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(fa!=-1 && low[v]>=dfn[u]) cut[u]=1;
            if(fa==-1 && child>=2) cut[u]=1;
        }
        else if(v!=fa){
            low[u]=min(low[u],dfn[v]);
        }
    }
}

模板题:hdu1269 迷宫城堡

桥:
1.对于节点\(u\),如果存在一个子节点\(v\),有\(low[v]>dfn[u]\),说明删除\(u\)\(v\)之间的边之后,\(v\)无法和\(u\)及其的祖先节点连通,所以\(u\)\(v\)之间的边为桥
2.重边一定不是桥,判断一条边是否为桥的时候需要判断是否有重边

const int maxn=1010,maxm=2000010;
int dfn[maxn],low[maxn],dfscnt,ans;
int edge_cnt[maxn][maxn];
vector<PII> bridge;

void tarjan(int u,int fa){
    dfn[u]=low[u]=++dfscnt;
    for(int i=head[u];~i;i=nxt[i]){
        int v=to[i],w=weight[i];
        if(!dfn[v]){
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u] && edge_cnt[u][v]==1) bridge.push_back({u,v});
        }
        else if(v!=fa){
            low[u]=min(low[u],dfn[v]);
        }
    }
}

模板题:hdu4738 Caocao's Bridges
割点和桥的关系
1.有割点不一定存在桥,有桥一定存在割点
2.桥一定是连接割点的边

posted @ 2020-08-31 22:56  fxq1304  阅读(106)  评论(0编辑  收藏  举报