双连通分量 模板

来源:互联网 发布:linux traceroute 端口 编辑:程序博客网 时间:2024/04/30 07:45
  1. bcc的全称是biconnected component,双连通分量,点双连通关注的是不包含割点的连通分量,边双连通关注的是不包含桥的连通分量。
  2. 点双连通例题:UVALive 5135。边双连通例题:poj 3352。
  3. 边双连通分量巧妙利用isB数组,空间换时间,也大大降低了模板的复杂度,解决了标记边难的问题。
//点双连通分量bool cut[maxn];int low[maxn], dfn[maxn], bccno[maxn], clocks, bcc_cnt;vector<int> G[maxn], bcc[maxn];stack<Edge> S;void tarjan(int u, int fa){    low[u] = dfn[u] = ++clocks;    int child = 0;    for(int i = 0; i < G[u].size(); ++i){        int v = G[u][i];        Edge e = Edge(u, v);        if(!dfn[v]){            S.push(e);            child++;            tarjan(v, u);            low[u] = min(low[u], low[v]);            if(low[v] >= dfn[u]) {                cut[u] = true;                bcc_cnt++;  bcc[bcc_cnt].clear();//bcc >= 1;                while(1){                    Edge t = S.top();  S.pop();                    if(bccno[t.u] != bcc_cnt){                        bcc[bcc_cnt].push_back(t.u);                        bccno[t.u] = bcc_cnt;                    }                    if(bccno[t.v] != bcc_cnt){                        bcc[bcc_cnt].push_back(t.v);                        bccno[t.v] = bcc_cnt;                    }                    if(t.u==u && t.v==v)  break;                }            }        }        else if(fa!=v && low[u]>dfn[v]) {            S.push(e);            low[u] = dfn[v];        }    }    if(fa==-1)        cut[u] = (child>=2) ? true : false;}//边双连通分量const int maxn = 1005;int n, times, bcc_cnt, dfn[maxn], low[maxn], bccno[maxn];vector<int> G[maxn];bool isB[maxn][maxn];void tarjan(int u, int fa){//找到桥    dfn[u] = low[u] = ++times;    for(int i = 0; i < G[u].size(); ++i){        int v = G[u][i];        if(!dfn[v]){            tarjan(v, u);            low[u] = min(low[u], low[v]);            if(low[v] > dfn[u])                isB[u][v] = isB[v][u] = true;        }        else if(fa != v)            low[u] = min(low[u], dfn[v]);    }}void dfs(int idx){//给边双连通分量标记    dfn[idx] = 1;    bccno[idx] = bcc_cnt;    for(int i = 0; i < G[idx].size(); ++i){        int v = G[idx][i];        if(isB[idx][v])            continue;        if(!dfn[v])            dfs(v);    }}void find_ebcc(){    bcc_cnt = times = 0;    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(bccno,0,sizeof(bccno));    memset(isB,0,sizeof(isB));    for(int i = 1; i <= n; ++i){//求出桥        if(!dfn[i]){            bcc_cnt++;            tarjan(i, -1);        }    }    memset(dfn,0,sizeof(dfn));    for(int i = 1; i <= n; ++i){//将点标记        if(!dfn[i]){            bcc_cnt++;            dfs(i);        }    }}
1 0
原创粉丝点击