POJ1523(求割点)
割点:删掉它之后(删掉所有跟它相连的边),图必然会分裂成两个或两个以上的子图。
一个顶点u是割点,当且仅当满足(1)或(2)
(1) u为树根,且u至少有两个子女
(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得low[v]>=dfn[u]
dfn[i]表示DFS 过程中到达点i 的时间,low[i]表示能通过其他边回到其祖先的最早时间
邻接表版本
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 using namespace std; 7 #define N 1005 8 #define M 100000 9 struct Edge 10 { 11 int v,next; 12 Edge(){} 13 Edge(int V,int NEXT):v(V),next(NEXT){} 14 }edge[M]; 15 int size,head[N]; 16 int nodes,son,index; 17 int dfn[N],low[N],subnets[N]; 18 void Init() 19 { 20 nodes = son = 0; 21 size = index = 0; 22 memset(subnets,0,sizeof(subnets)); 23 memset(head,-1,sizeof(head)); 24 memset(dfn,0,sizeof(dfn)); 25 memset(low,0,sizeof(low)); 26 } 27 void InsertEdge(int u,int v) 28 { 29 edge[size] = Edge(v,head[u]); 30 head[u] = size++; 31 } 32 void Trajan(int u) 33 { 34 low[u] = dfn[u] = ++index; 35 for(int i=head[u]; i!=-1; i=edge[i].next) 36 { 37 int v = edge[i].v; 38 if(!dfn[v]) 39 { 40 Trajan(v); 41 low[u] = min(low[u],low[v]); 42 if(low[v] >= dfn[u]) 43 { 44 if(u != 1) subnets[u]++; 45 if(u == 1) son++; 46 } 47 } 48 else low[u] = min(low[u],dfn[v]); 49 } 50 } 51 int main() 52 { 53 int cas = 1; 54 int flag,u,v; 55 while(scanf("%d",&u)&&u) 56 { 57 Init(); 58 scanf("%d",&v); 59 if(u > nodes) nodes = u; 60 if(v > nodes) nodes = v; 61 InsertEdge(u,v); 62 InsertEdge(v,u); 63 while(scanf("%d",&u)&&u) 64 { 65 scanf("%d",&v); 66 if(u > nodes) nodes = u; 67 if(v > nodes) nodes = v; 68 InsertEdge(u,v); 69 InsertEdge(v,u); 70 } 71 Trajan(1); 72 if(son > 1) subnets[1] = son-1; 73 if(cas > 1) printf("\n"); 74 printf("Network #%d\n",cas++); 75 flag = 0; 76 for(int i=1; i<=nodes; i++) 77 { 78 if(subnets[i]) 79 { 80 flag = 1; 81 printf(" SPF node %d leaves %d subnets\n",i,subnets[i]+1); 82 } 83 } 84 if(!flag) printf(" No SPF nodes\n"); 85 } 86 return 0; 87 }
邻接矩阵版本
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 using namespace std; 7 #define N 1005 8 int Edge[N][N]; 9 int dfn[N]; 10 int low[N]; 11 int nodes; 12 int index; 13 int son; 14 int subnets[N]; 15 16 void Trajan(int u) 17 { 18 low[u] = dfn[u] = ++index; 19 for(int v=1; v<=nodes; v++) 20 { 21 if(Edge[u][v]) 22 { 23 if(!dfn[v]) 24 { 25 Trajan(v); 26 low[u] = min(low[u],low[v]); 27 if(low[v] >= dfn[u]) 28 { 29 if(u != 1) subnets[u]++; 30 if(u == 1) son++; 31 } 32 } 33 else low[u] = min(low[u],dfn[v]); 34 } 35 } 36 } 37 38 void Init() 39 { 40 nodes = son = 0; 41 index = 0; 42 memset(subnets,0,sizeof(subnets)); 43 memset(dfn,0,sizeof(dfn)); 44 memset(low,0,sizeof(low)); 45 memset(Edge,0,sizeof(Edge)); 46 } 47 48 int main() 49 { 50 int flag,u,v; 51 int cas = 1; 52 while(scanf("%d",&u)&&u) 53 { 54 Init(); 55 scanf("%d",&v); 56 if(u > nodes) nodes = u; 57 if(v > nodes) nodes = v; 58 Edge[u][v] = Edge[v][u] = 1; 59 while(scanf("%d",&u)&&u) 60 { 61 62 scanf("%d",&v); 63 if(u > nodes) nodes = u; 64 if(v > nodes) nodes = v; 65 Edge[u][v] = Edge[v][u] = 1; 66 } 67 Trajan(1); 68 if(cas > 1) printf("\n"); 69 if(son > 1) subnets[1] = son - 1 ; 70 printf("Network #%d\n",cas++); 71 flag = 0; 72 for(int i=1; i<=nodes; i++) 73 { 74 if(subnets[i]) 75 { 76 flag = 1; 77 printf(" SPF node %d leaves %d subnets\n",i,subnets[i]+1); 78 } 79 } 80 if(!flag) printf(" No SPF nodes\n"); 81 } 82 return 0; 83 }