无向图连通性——割点
搜索方式为建立bfs搜索树,并更新dfn[ ]和low[ ]。与求强连通块类似,但割点u 的判断条件为:对于节点u 和他的子节点v,满足 low[v]>= dfn[u]。特别的,如果节点u 是搜索树的根节点,则u 是割点当且仅当搜索树上至少有两个子节点v1,v2 满足上述条件。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<stack> 6 using namespace std; 7 const int maxv= 110; 8 const int maxe= 5010; 9 10 struct ENode 11 { 12 int to; 13 int Next; 14 }; 15 ENode edegs[maxe]; 16 int Head[maxv], tnt; 17 void init() 18 { 19 memset(Head, -1, sizeof(Head)); 20 tnt= -1; 21 } 22 void Add_ENode (int a, int b) 23 { 24 ++ tnt; 25 edegs[tnt].to= b; 26 edegs[tnt].Next= Head[a]; 27 Head[a]= tnt; 28 ++ tnt; 29 edegs[tnt].to= a; 30 edegs[tnt].Next= Head[b]; 31 Head[b]= tnt; 32 } 33 34 int dfn[maxv]; //深度优先搜索中顶点被访问的时间 35 int low[maxv]; //顶点v 和它的邻接点中low[]的最小值 36 int temp[maxv]; //判断节点是否已被访问过(0-未访问 1-已访问未删除 2-已访问已删除) 37 int cut[maxv]; //判断点i 是否为割点 38 int root; //子树的根节点 39 int tarjanbfs(int u, int &lay) 40 { 41 dfn[u]= ++ lay; 42 low[u]=lay; 43 int flag= 0; 44 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 45 { 46 int v= edegs[k].to; 47 if (! dfn[v]) 48 { 49 tarjanbfs(v, lay); 50 low[u]= min(low[u], low[v]); 51 if (low[v]>= dfn[u]) 52 { 53 flag ++; 54 if (u!= root|| flag> 1) cut[u]= 1; 55 } 56 } 57 else 58 { 59 low[u]= min(low[u], dfn[v]); 60 } 61 } 62 } 63 64 void tarjan(int n) 65 { 66 int lay= 0; 67 memset(low, 0, sizeof(low)); 68 memset(cut, 0, sizeof(cut)); 69 for (int i= 1; i<= n; i ++) 70 { 71 if (! dfn[i]) root= i, tarjanbfs(root, lay); 72 } 73 } 74 75 int main() 76 { 77 int n, m; 78 int x, y; 79 while (~ scanf("%d %d", &n, &m)) 80 { 81 init(); 82 for (int i= 0; i< m; i ++) 83 { 84 scanf("%d %d", &x, &y); 85 Add_ENode(x, y); 86 } 87 tarjan(n); 88 89 /**/ 90 for (int i = 1; i <= n; i++) 91 { 92 printf("%d%c", cut[i], i != n ? ' ' : ' '); 93 } 94 for (int i= 1; i<= n; i ++) 95 { 96 printf("%d%c", low[i], i != n ? ' ' : ' '); 97 } 98 for (int i= 1; i<= n; i ++) 99 { 100 printf("%d%c", dfn[i], i != n ? ' ' : ' '); 101 } 102 } 103 return 0; 104 }