这是割顶题中的极为基础的一道,就是用了《数据结构》中的关节点(P178),或者说是刘汝佳的《算法艺术与信息学竞赛》中的割顶(P285)。我的理解和解释,就是如果当前结点的某个子结点的祖先的最低遍历编号不小于当前结点的遍历编号(这个解释必须这么长,因为无论是哪本书,对此的解释都是差不多的),那么当前结点就是所要找的割顶,而且割的是之前提及的某个子结点与在当前结点前被遍历的祖先的联系。
这题可以直接套《数据结构》的FindArticul、DFSArticul函数,但是还要做的是思考怎样统计割顶的把整个图割成子连通分量的个数,因为题目要求求出割顶的同时,也要输出割顶把图分成多少部分。如果没有,就输出没有。
这题要注意的是如果只输入一个0,这个不是一组数据,是不应该被处理的。我一开始wa的几次就只是因为这个,于是后来只好找题解帮忙。可是在我看到解题代码前,我找到一个标准数据,直接发现这个无聊的,但是poj又没有提及的注意事项。
我的代码除了头文件比较长,其他的是模仿《数据结构》的算法的,所以应该还是挺容易理解的:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include "cstdio" 2 #include "cstdlib" 3 #include "cstring" 4 #include "cmath" 5 #include "cctype" 6 #include "vector" 7 #include "set" 8 #include "map" 9 #include "string" 10 #include "algorithm" 11 #include "stack" 12 #include "queue" 13 14 #define INF 0x7fffffff 15 #define reset(a) memset(a, 0, sizeof(a)) 16 #define copy(a, b) memcpy(a, b, sizeof(b)) 17 #define PI acos(-1) 18 #define FMAX (1E300) 19 #define MAX 1000000000 20 #define feq(a, b) (fabs((a)-(b))<1E-6) 21 #define flq(a, b) ((a)<(b)||feq(a, b)) 22 #define MAXN 10005 23 #define BASE 137 24 #define PASS puts("pass") 25 #define filein freopen("test.in", "r", stdin) 26 #define fileout freopen("test.out", "w", stdout) 27 28 using namespace std; 29 30 int e[1001][1001]; 31 int cnt, low[1001], vis[1001]; 32 int spf[1001]; 33 set<int> S; 34 35 void dfs(int node){ 36 int min = ++cnt; 37 38 vis[node] = cnt; 39 for (int i = 1; i <= e[node][0]; i++){ 40 if (!vis[e[node][i]]){ 41 dfs(e[node][i]); 42 if (min > low[e[node][i]]) 43 min = low[e[node][i]]; 44 if (low[e[node][i]] >= vis[node]) 45 spf[node]++; 46 } 47 else if (min > vis[e[node][i]]) 48 min = vis[e[node][i]]; 49 } 50 low[node] = min; 51 } 52 53 int main(){ 54 int a, b, CASE = 1; 55 56 //filein; 57 //fileout; 58 reset(e); 59 S.clear(); 60 while (1){ 61 if (!~scanf("%d", &a)) 62 return 0; 63 if (a){ 64 scanf("%d", &b); 65 e[a][++e[a][0]] = b; 66 e[b][++e[b][0]] = a; 67 S.insert(a); 68 S.insert(b); 69 } 70 else{ 71 if (!S.size()) 72 continue; 73 if (CASE != 1) 74 printf("\n"); 75 reset(vis); 76 reset(spf); 77 reset(low); 78 bool pnt = false; 79 cnt = 1; 80 printf("Network #%d\n", CASE++); 81 82 int begin; 83 84 for (begin = 1; begin <= 1000; begin++) 85 if (S.count(begin)) 86 break; 87 low[begin] = vis[begin] = 1; 88 for (int i = 1; i <= e[begin][0]; i++){ 89 if (!vis[e[begin][i]]){ 90 dfs(e[begin][i]); 91 if (cnt < S.size()) 92 spf[begin]++; 93 } 94 } 95 for (int i = 1; i <= 1000; i++){ 96 if (spf[i]){ 97 printf(" SPF node %d leaves %d subnets\n", i, spf[i] + 1); 98 pnt = true; 99 } 100 } 101 if (!pnt) 102 printf(" No SPF nodes\n"); 103 reset(e); 104 S.clear(); 105 } 106 } 107 }
——written by Lyon