點雙連通分量和邊雙連通分量學習筆記


點雙連通分量和邊雙連通分量學習筆記

1.簡介:

對於一個連通圖,如果任意兩點至少存在兩條點不重復路徑,則稱這個圖為點雙連通的(簡稱雙連通);如果任意兩點至少存在兩條邊不重復路徑,則稱該圖為邊雙連通的。點雙連通圖的定義等價於任意兩條邊都同在一個簡單環中,而邊雙連通圖的定義等價於任意一條邊至少在一個簡單環中。對一個無向圖,點雙連通的極大子圖稱為點雙連通分量(簡稱雙連通分量),邊雙連通的極大子圖稱為邊雙連通分量

而在每一個點雙連通圖中,內部無割點;

在每一個邊雙連通圖中,內部無橋。

如圖:

 

 

1、2、3,2、4、5為兩個點雙連通分量,1、2、3、4、5卻在一個邊雙連通分量中;其中,3為割點。

而第二個圖中,2-6邊為橋。

 

2.性質:
  <1>.點雙連通分量:
     (1).點雙連通分量之間以割點連接,且兩個點雙連通分量之間有且只有一個割點。
         證明:
            若兩個點雙連通分量之間共用兩個點,則刪除其中任意一個點,所有點依舊連通。
         如圖:

                        

     (2).每一個割點可任意屬於多個點雙連通分量,因此求點雙連通分量時,可能包含重復的點。
             (3).只有一條邊連通的兩個點也是一個點雙連通分量,如:

        

         所以,在下圖中,存在(1、2、3),(3、4),(4、5、6)三個點雙連通分量。

         

     (4).對於此點為根的情況,第一個兒子也屬於點雙連通分量,故不能用判斷割點的方法來判斷,

         只要dfn[父]<=low[子],便可將其加入點雙:

        

 

                在此圖中,1、2、3、4在同一個點雙連通分量里,但2是1的第一個兒子

    (5).對於刪去此點不會不與祖輩連通的兒子,在處理其他兒子的點雙連通分量時,不能將其刪去,如。

        

 

                    1、2、3共同構成一個點雙連通分量,不能在處理4、5、6是將其刪去。

                    所以代碼不該為:

                    

         while(s[top]!=u) ++siz[tot]=s[top],num[s[top]]=tot,--top;

                   而應是

                   

        v=e[i].to;
        while(s[top+1]!=v) ++siz[tot],num[s[top]]=tot,--top;

       <2>.邊雙連通分量:

        可將圖看作森林,節點為邊雙連通分量,樹邊為橋:

               

        第二張圖是第一張圖中的點雙連通分量縮點后的樣子。

 

     邊雙連通分量沒有什么性質,反正也很簡單。                   ——LY巨佬

3.做法和代碼:

    日復一日的神仙tarjan算法:

     1>.點雙連通分量:

        用棧來儲存,按dfs序來加點,將此點與low小於其dfn的點放入一個點雙連通分量中(注:此點不退棧)

        

 1 void tarjan(int u)
 2 {
 3     dfn[u]=low[u]=++deep; s[++top]=u; int o=0,v;
 4     for(int i=head[u];i;i=e[i].nxt)
 5     {
 6         v=e[i].to;
 7         if(!dfn[v])
 8         {
 9             ++o;
10             tarjan(v),low[u]=min(low[u],low[v]);
11             if(low[v]>=dfn[u])
12             {
13                 if(u!=fa) cut[u]=1; ++tot;
14                 while(s[top+1]!=v) num[tot][++siz[tot]]=s[top],id[s[top]]=tot,--top;
15                 num[tot][++siz[tot]]=u;//將id[u]默認屬於它父親的tot了
16             }
17         }
18         else low[u]=min(low[u],dfn[v]);
19     }
20     if(u==fa&&o>=2) cut[u]=1;
21 }

 

     2>.邊雙連通分量:

        刪去橋就行了。

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=5006,M=10006;
 4 int head[N],cnt=1,n,m,t1,t2,book[N],dfn[N],low[N],deep=0,v[M*2],f[N],tot=0,d[N],g[N],p=0,num[N][N],siz[N];
 5 map<int,int> ha[N];
 6 int getf(int u){return g[u]==u?u:g[u]=getf(g[u]);}
 7 void merge(int u,int v)
 8 {
 9     u=getf(u); v=getf(v);
10     if(u==v) return;
11     g[u]=v;
12 }
13 struct edge
14 {
15     int nxt,to;
16 }e[M*2]; 
17 inline int read()
18 {
19     int T=0,F=1; char ch=getchar();
20     while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
21     while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
22     return F*T;
23 }
24 inline void add(int u,int v){e[++cnt].nxt=head[u]; e[cnt].to=v; head[u]=cnt;} 
25 void tarjan(int u)
26 {
27     dfn[u]=low[u]=++deep;
28     for(int i=head[u];i;i=e[i].nxt)
29     {
30         if(v[i^1]||v[i]) continue;
31         if(!dfn[e[i].to]) v[i]=1,f[e[i].to]=u,tarjan(e[i].to),low[u]=min(low[u],low[e[i].to]);
32         else low[u]=min(low[u],dfn[e[i].to]);
33     }
34 }
35 int main()
36 {
37     n=read(),m=read();
38     for(int i=1;i<=n;++i) g[i]=i;
39     for(int i=1;i<=m;++i) t1=read(),t2=read(),add(t1,t2),add(t2,t1);
40     for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
41     for(int i=1;i<=n;++i) if(f[i]&&low[i]>dfn[f[i]]) ++tot,ha[i][f[i]]=1,ha[f[i]][i]=1;
42     for(int i=1;i<=n;++i)
43         for(int j=head[i];j;j=e[j].nxt) if(ha[i].find(e[j].to)==ha[i].end()) merge(i,e[j].to);
44     for(int i=1;i<=n;++i) g[i]=getf(i);
45     for(int i=1;i<=n;++i)
46     {
47         if(!book[g[i]]) ++p,d[g[i]]=p,book[g[i]]=1;
48         g[i]=d[g[i]],num[g[i]][++siz[g[i]]]=i;
49     } 
50     printf("共有%d個邊雙連通分量\n",p);
51     for(int i=1;i<=p;++i)
52     {
53         printf("第%d個邊雙連通分量共有%d個點",i,siz[i]);
54         for(int j=1;j<=siz[i];++j) printf("%d ",num[i][j]);
55         printf("\n");
56     }
57     return 0;
58 }

 

 

 

        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM