割点和桥
割点:无向图中,如果删除某个点以及和它相邻的所有边之后,图中连通分量数增加,则称该点为割点
桥:无向图中,如果删除某条边之后,图中连通分量数增加,则称该边为桥
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.桥一定是连接割点的边