1. 程式人生 > 其它 >Centos系統目錄詳解

Centos系統目錄詳解

雙連通分量

定義

對於無向圖中兩點\(u,v\),若無論刪去哪條邊都不能使其不連通,則稱\(u,v\)邊雙連通

對於無向圖中兩點\(u,v\),若無論刪去哪個點都不能使其不連通,則稱\(u,v\)點雙連通

邊雙連通

我們發現使兩點不連通的邊其實就是橋(割邊)

所以我們只需要把橋刪了即可

void tarjan(int now,int fa) {
    dfn[now]=low[now]=++cnt;
    for (int i=beg[now];i;i=e[i].nex) {
        int nex=e[i].to;
        if (nex==fa) continue;
        if (!dfn[nex]) {
            tarjan(nex,now);
            chkmin(low[now],low[nex]);
            if (dfn[now]<low[nex]) e[i^1].cut=e[i].cut=1;
        }
        else chkmin(low[now],dfn[nex]);
    }
}
void dfs(int now,int fa,int C) {
    col[C].push_back(now);
    bel[now]=C;
    for (int i=beg[now];i;i=e[i].nex) {
        int nex=e[i].to;
        if (nex==fa || bel[nex] || e[i].cut) continue;
        dfs(nex,now,C);
    }
}

點雙連通

我們發現,兩個點雙一定有一個割點連線,且這個割點被兩個點雙包含,所以我們可以直接根據強連通分量的方式,把點入棧,然後找到割點就不停彈出點,並全部存入點雙

void tarjan(int now,int Fa) {
    dfn[now]=low[now]=++cnt;st[++top]=now;
    if (now==Fa && !beg[now])  col[++tot].push_back(now);
    for (int i=beg[now];i;i=e[i].nex) {
        int nex=e[i].to;
        if (nex==Fa) continue;
        if (!dfn[nex]) {
            tarjan(nex,now);
            chkmin(low[now],low[nex]);
            if (dfn[now]<=low[now]) {
                ++tot;
                while(1) {
                    col[++tot].push_back(st[top]);
                    if (st[top]==nex) {top--;break;}
                    top--;
                }
                col[tot].push_back(now);
            }
        }
        else chkmin(low[now],dfn[nex]);
    }
}

圓方樹

圓方樹主要用於處理仙人掌圖(每條邊在不超過一個簡單環中的無向圖)的問題

在剛剛的點雙基礎上,我們來構建一棵圓方樹

我們將原來的點看做一個圓點,對於一個點雙建一個方點,方點向該點雙裡的每個圓點連邊

那麼,每個點雙就是一個菊花,然後整張圖是由割點連線很多菊花

當原圖是一個聯通圖時,我們構建的圖就是一棵樹

然後,我們考慮如何實現這個構建過程

由於圓方樹基於點雙,所以在求點雙的過程中可以建出這棵樹

void tarjan(int now,int fa) {
    dfn[now]=low[now]=fa;
    if (now==fa && !beg[now]) {
        cntcol++;
        E[cntcol].push_back(now);
        E[now].push_back(cntcol);
    }
    st[++top]=now;
    for (int i=beg[now];i;i=e[i].nex) {
        int nex=e[i].to;
        if (nex==fa) continue;
        if (!dfn[nex]) {
            tarjan(nex,now);
            chkmin(low[now],low[nex]);
            if (low[nex]<=dfn[now]) {
                cntcol++;
                while(1) {
                    E[cntcol].push_back(st[top]);
                    E[st[top]].push_back(cntcol);
                    if (st[top]==nex) {top--;break;}
                    top--;
                }
                E[cntcol].push_back(now);
                E[now].push_back(cntcol);
            }
            else chkmin(low[now],dfn[nex]);
        }
    }
}

例題

[APIO2018]鐵人兩項