poj1144 Network——图论,求割点

传说中的模板题。

Tarjan算法求割点。

Tarjan算法是求割点算法里边一种十分易于理解的算法。我们知道一个无向图在dfs的过程中会产生一棵生成树,剩下的弦必然不会跨越子树,所以我们通过一遍dfs就能记录下一个点能够返回的它最早的祖先的编号。

对于某个点,如果它以及它的子孙结点不能返回它祖先的结点,那么这个点很明显就是割点。


网上的很多题解都没有讲清楚这题什么意思,而这题的输入也十分的坑爹,再加上我是用VC写的。于是一次CE、一次RE、第三次AC(←虽然代码本身没问题)。

这份代码在图论题目里是十分有代表性的。

题目的意思就是简单的让你求割点的数目。

输入的第一个数字代表点的个数。

然后的几行里面,每行的第一个数字代表第n个点,它们联通到之后的数字的点上。

如果第一个数字为0,代表这组数据结束了。

如果点的个数为0,表示输入结束了。

1
2
3
5
5 1 2 3 4
0

对于上面这组数据,表示有5个点,其中第5个点连接到第1、2、3、4个点。


这就是坑了我很久的地方。。。。

下面是我的AC代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream> 
#include <vector>
#include <sstream>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
struct info{
int len;
int dclock;
int *cut;
int *low;
int *dfn;
info(int n){
len = n;
dclock = 1;
cut = new int[n];
low = new int[n];
dfn = new int[n];
memset(cut, 0, sizeof(int)*len);
memset(dfn, -1, sizeof(int)*len);
}
~info(){
delete[] cut;
delete[] low;
delete[] dfn;
}
};
void dfs(info &tree, vector< vector<int> > &map, int u, int fa){
int son = 0;
tree.dfn[u] = tree.low[u] = tree.dclock++;
for (int i = 0; i < map[u].size(); i++){
int v = map[u][i];
if (tree.dfn[v]<0){
dfs(tree, map, v, u);
son++;
tree.low[u] = min(tree.low[u], tree.low[v]);
if ((fa < 0 && son > 1) (fa >= 0 && tree.low[v] >= tree.dfn[u]))
tree.cut[u] = 1;
}
else if (tree.low[u] > tree.low[v] && v != fa){
tree.low[u] = min(tree.low[u], tree.dfn[v]);
}
}
}
int solve(int n){
vector<vector<int>> map;
map.resize(n);
int s, u;
while (1){
string temp;
getline(cin, temp);
istringstream buf(temp);
buf >> s;
if (s == 0) break;
while (buf >> u){
map[s - 1].push_back(u - 1);
map[u - 1].push_back(s - 1);
}
}
info tree(n);
for (int i = 0; i < n; i++){
if (map[i].size()>0){
dfs(tree, map, i, -1);
break;
}
}
int cnt = 0;
for (int i = 0; i < n; i++){
if (tree.cut[i] == 1)
cnt++;
}
return cnt;
}

int main(int agrc, char *agrv[]){
int n;
while (cin >> n, n){
cout << solve(n) << endl;
}
}