边双连通模板

双连通 缩点 求桥模版:

  1. #include <stdio.h>  
  2. #include <iostream>  
  3. #include <algorithm>  
  4. #include <string.h>  
  5. #include <queue>  
  6. #include <vector>  
  7. using namespace std;  
  8. #define N 100005  
  9. #define M 200300  
  10. #define inf 10000000  
  11. struct Edge{  
  12.     int from,to,next;  
  13.     bool cut;  
  14. }edge[2*M];  
  15. int head[N],edgenum;  
  16. int Low[N],DFN[N],Stack[N];//Belong数组的值是1~block  
  17. int Index,top;  
  18. int Belong[N],block;//新图的连通块标号(1~block)  
  19. bool Instack[N];  
  20. int bridge; //割桥数量  
  21.   
  22. void addedge(int u,int v){  
  23.     Edge E={u,v,head[u],0}; edge[edgenum]=E; head[u] = edgenum++;  
  24.     Edge E2={v,u,head[v],0};edge[edgenum]=E2;head[v] = edgenum++;  
  25. }  
  26. void Tarjan(int u,int pre){  
  27.     int v;  
  28.     Low[u] = DFN[u] = ++Index;  
  29.     Stack[top++] = u;  
  30.     Instack[u] = true;  
  31.     for(int i = head[u]; ~i ;i = edge[i].next){  
  32.         v = edge[i].to;  
  33.         // 如果重边有效的话下面这句改成: if(v == pre && pre_num == 0){pre_num++;continue;} pre_num在for上面定义 int pre_num=0;  
  34.         if( v == pre )continue;  
  35.         if( !DFN[v] ){  
  36.             Tarjan(v,u);  
  37.             if(Low[u] > Low[v])Low[u] = Low[v];  
  38.             if(Low[v] > Low[u]){  
  39.                 bridge++;  
  40.                 edge[i].cut = true;  
  41.                 edge[i^1].cut = true;  
  42.             }  
  43.         }  
  44.         else if(Instack[v] && Low[u] > DFN[v])Low[u] = DFN[v];  
  45.     }  
  46.     if(Low[u] == DFN[u]){  
  47.         block++;  
  48.         do{  
  49.             v = Stack[--top];  
  50.             Instack[v] = false;  
  51.             Belong[v] = block;  
  52.         }while( v != u );  
  53.     }  
  54. }  
  55. void work(int l, int r){  
  56.     memset(DFN,0,sizeof(DFN));  
  57.     memset(Instack,false,sizeof(Instack));  
  58.     Index = top = block = bridge = 0;  
  59.     for(int i = l; i <= r; i++)if(!DFN[i])Tarjan(i,i);  
  60. }  
  61. vector<int>G[N];//点标从1-block  
  62. void suodian(){  
  63.     for(int i = 1; i <= block; i++)G[i].clear();  
  64.     for(int i = 0; i < edgenum; i+=2){  
  65.         int u = Belong[edge[i].from], v = Belong[edge[i].to];  
  66.         if(u==v)continue;  
  67.         G[u].push_back(v), G[v].push_back(u);  
  68.     }  
  69. }  
  70. void init(){edgenum = 0; memset(head,-1,sizeof(head));}  


求割点和桥 (binshen模版)

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <iostream>  
  4. #include <algorithm>  
  5. #include <vector>  
  6. #include <queue>  
  7. #include <set>  
  8. #include <map>  
  9. #include <string>  
  10. #include <math.h>  
  11. #include <stdlib.h>  
  12. #include <time.h>  
  13. using namespace std;  
  14. const int INF = 0x3f3f3f3f;  
  15. /* 
  16. *  求 无向图的割点和桥 
  17. *  可以找出割点和桥,求删掉每个点后增加的连通块。 
  18. *  需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 
  19. */  
  20. #define N 10005  
  21. #define M 200010  
  22. struct Edge{  
  23.     int to,next,w;  
  24.     bool cut;//是否为桥的标记  
  25. }edge[M*2];  
  26. int head[N],edgenum;  
  27. int Low[N],DFN[N],Stack[N],Index,top;  
  28. bool Instack[N];  
  29. bool cut[N]; //是否为割点  
  30. int add_block[N];//删除i点后增加的连通块数量为add_block[i]  
  31. int bridge;  //桥数量  
  32.   
  33. void addedge(int u,int v,int w)  
  34. {  
  35.     edge[edgenum].to = v;edge[edgenum].next = head[u];edge[edgenum].cut = false;  
  36.     edge[edgenum].w = w;  
  37.     head[u] = edgenum++;  
  38.     edge[edgenum].to = u;edge[edgenum].next = head[v];edge[edgenum].cut = false;  
  39.     edge[edgenum].w = w;  
  40.     head[v] = edgenum++;  
  41. }  
  42. void Tarjan(int u,int pre){  
  43.     int v;  
  44.     Low[u] = DFN[u] = ++Index;  
  45.     Stack[top++] = u;  
  46.     Instack[u] = true;  
  47.     int son = 0;  
  48.     int pre_num = 0;  
  49.     for(int i = head[u];i != -1;i = edge[i].next)  
  50.     {  
  51.         v = edge[i].to;  
  52.         //若重边无效则把下面这句换成 if(v == pre)continue;  
  53.         if(v == pre && pre_num == 0){pre_num++;continue;}  
  54.         if( !DFN[v] )  
  55.         {  
  56.             son++;  
  57.             Tarjan(v,u);  
  58.             if(Low[u] > Low[v])Low[u] = Low[v];  
  59.             //桥  
  60.             //一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u)<Low(v)。  
  61.             if(Low[v] > DFN[u])  
  62.             {  
  63.                 bridge++;  
  64.                 edge[i].cut = true;  
  65.                 edge[i^1].cut = true;  
  66.             }  
  67.             //割点  
  68.             //一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。  
  69.             //(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,  
  70.             //即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)  
  71.             if(u != pre && Low[v] >= DFN[u])//不是树根  
  72.             {  
  73.                 cut[u] = true;  
  74.                 add_block[u]++;  
  75.             }  
  76.         }  
  77.         else if( Low[u] > DFN[v])  
  78.              Low[u] = DFN[v];  
  79.     }  
  80.     //树根,分支数大于1  
  81.     if(u == pre && son > 1)cut[u] = true;  
  82.     if(u == pre)add_block[u] = son - 1;  
  83.     Instack[u] = false;  
  84.     top--;  
  85. }  
  86. void solve(int l, int r){ //点标区间为[l,r]  
  87.     memset(DFN,0,sizeof(DFN));  
  88.     memset(Instack,false,sizeof(Instack));  
  89.     memset(add_block,0,sizeof(add_block));  
  90.     memset(cut,false,sizeof(cut));  
  91.     Index = top = bridge = 0;  
  92.     for(int i = l;i <= r;i++)if(!DFN[i])Tarjan(i,i);  
  93. }  
  94. void init(){ edgenum = 0;  memset(head,-1,sizeof(head));}  




模版1:重边有效 白书模版:
  1. #include<stdio.h>  
  2. #include<iostream>  
  3. #include<string.h>  
  4. #include<algorithm>  
  5. #include<vector>  
  6. #include<math.h>  
  7. #include<queue>  
  8. #include<set>  
  9. using namespace std;  
  10. #define N 10050  
  11. #define M 200005  
  12.   
  13. int n,m;//n个点 m条边 点标从1开始  
  14. struct Edge{  
  15.     int from,to,val,nex;  
  16.     bool cut;//记录这条边是否为割边   
  17. }edge[2*M];//双向边则 edge[i]与edge[i^1]是2条反向边  
  18. int head[N],edgenum;//在一开始就要 memset(head,-1,sizeof(head)); edgenum=0;  
  19. int low[N],dfn[N],tarjin_time;  
  20. void add(int u,int v,int w){  
  21.     Edge E={u,v,w,head[u],0};  
  22.     edge[edgenum]=E;  
  23.     head[u]=edgenum++;  
  24.     Edge E2={v,u,w,head[v],0};  
  25.     edge[edgenum]=E2;  
  26.     head[v]=edgenum++;  
  27. }  
  28. void tarjin(int u,int pre)  
  29. {  
  30.     low[u]=dfn[u]= ++tarjin_time;  
  31.     int flag=1;//flag是阻止双向边的反向边 i和i^1  
  32.     for(int i=head[u];i!=-1;i=edge[i].nex)  
  33.     {  
  34.         int v=edge[i].to;  
  35.         if(flag&&v==pre)  
  36.         {  
  37.             flag=0;  
  38.             continue;  
  39.         }  
  40.         if(!dfn[v])  
  41.         {  
  42.             tarjin(v,u);  
  43.             if(low[u]>low[v])low[u]=low[v];  
  44.             if(low[v]>dfn[u])//是桥low[v]表示v能走到的最早祖先 有重边且u是v的最早祖先 则low[v]==dfn[u],所以不会当作桥  
  45.                 edge[i].cut=edge[i^1].cut=true;  
  46.         }  
  47.         else if(low[u]>dfn[v])low[u]=dfn[v];  
  48.     }  
  49. }  
  50. void find_edgecut()  
  51. {  
  52.     memset(dfn,0,sizeof(dfn));  
  53.     tarjin_time=0;  
  54.     for(int i=1;i<=n;i++)if(!dfn[i])tarjin(i,i);  
  55. }  
  56. void init(){memset(head, -1, sizeof head); edgenum = 0;}  


重边算1条:

  1. #include <stdio.h>  
  2. #include <algorithm>  
  3. #include <iostream>  
  4. #include <string.h>  
  5. #include <vector>  
  6. using namespace std;  
  7.   
  8. /* 
  9. *  求 无向图的割点和桥 
  10. *  可以找出割点和桥,求删掉每个点后增加的连通块。 
  11. *  这个模版是重边算1条 
  12. */  
  13. const int MAXN = 10010;  
  14. const int MAXM = 100010;  
  15. struct Edge{  
  16.     int to,next;  
  17.     bool cut;//是否为桥的标记  
  18. }edge[MAXM*2];  
  19. int head[MAXN],edgenum;  
  20. int Low[MAXN],DFN[MAXN],Stack[MAXN];  
  21. int Index,top;  
  22. bool Instack[MAXN];  
  23. bool cut[MAXN]; //点是否为割点  
  24. int add_block[MAXN];//删除一个点后增加的连通块  
  25. int bridge;  
  26. void add(int u,int v){  
  27.     edge[edgenum].to = v;edge[edgenum].next = head[u];edge[edgenum].cut = false;  
  28.     head[u] = edgenum++;  
  29.     edge[edgenum].to = u;edge[edgenum].next = head[v];edge[edgenum].cut = false;  
  30.     head[v] = edgenum++;  
  31. }  
  32. void Tarjan(int u,int pre){  
  33.     int v;  
  34.     Low[u] = DFN[u] = ++Index;  
  35.     Stack[top++] = u;  
  36.     Instack[u] = true;  
  37.     int son = 0;  
  38.     for(int i = head[u];i != -1;i = edge[i].next)  
  39.     {  
  40.         v = edge[i].to;  
  41.         if(v == pre)continue;  
  42.         if( !DFN[v] )  
  43.         {  
  44.             son++;  
  45.             Tarjan(v,u);  
  46.             if(Low[u] > Low[v])Low[u] = Low[v];  
  47.             //桥  
  48.             //一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u)<Low(v)。  
  49.             if(Low[v] > DFN[u])  
  50.             {  
  51.                 bridge++;  
  52.                 edge[i].cut = true;  
  53.                 edge[i^1].cut = true;  
  54.             }  
  55.             //割点  
  56.             //一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。  
  57.             //(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,  
  58.             //即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)  
  59.             if(u != pre && Low[v] >= DFN[u])//不是树根  
  60.             {  
  61.                 cut[u] = true;  
  62.                 add_block[u]++;  
  63.             }  
  64.         }  
  65.         else if( Low[u] > DFN[v])  
  66.              Low[u] = DFN[v];  
  67.     }  
  68.     //树根,分支数大于1  
  69.     if(u == pre && son > 1)cut[u] = true;  
  70.     if(u == pre)add_block[u] = son - 1;  
  71.     Instack[u] = false;  
  72.     top--;  
  73. }  
  74.   
  75. void solve(int n){  
  76.     memset(DFN,0,sizeof(DFN));  
  77.     memset(Instack,false,sizeof(Instack));  
  78.     memset(add_block,0,sizeof(add_block));  
  79.     memset(cut,false,sizeof(cut));  
  80.     Index = top = 0;  
  81.     bridge = 0;  
  82.     for(int i = 1;i <= n;i++)if(!DFN[i]) Tarjan(i,i);  
  83. }  
  84. void init(){edgenum = 0; memset(head,-1,sizeof(head));} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值