题意:给出一个无向图,判断是否任意两点间都存在至少3条互相独立的路,独立指公共顶点只有起点和终点。
算法:枚举每个点,删去后用Tarjan判断图中是否存在割点,如果存在则该图不满足三连通性。Tarjan中保存搜索树,多子树的根节点为割点;
dfs顺序为节点编号,dp得到每个子树通过回边能回到的最小编号,若某点的子树们能回到的点大于等于自己,则该点为割点。
转自:yogykwan
1 #include <cstdio>
2 #include <cstring>
3 #include <vector>
4 #include <algorithm>
5
6 using namespace std;
7
8 int del, root;
9 bool cut;
10 int dfn[510], low[510];
11
12 vector<int> e[510];
13 int n, m;
14 int tot;
15
16 void Tarjan(int u, int p) { // 当前节点,父亲节点
17 if (cut) return;
18 dfn[u] = low[u] = ++tot;
19 int son = 0;
20 for (vector<int>::iterator it = e[u].begin(); it != e[u].end(); ++it) {
21 int v = *it;
22 if (v == p || v == del) continue;
23 if (!dfn[v]) {
24 ++son;
25 Tarjan(v, u);
26 low[u] = min(low[u], low[v]);
27 if ((u == root && son > 1) || (u != root && low[v] >= dfn[u])) { // 割点条件
28 cut = 1;
29 return;
30 }
31 } else {
32 low[u] = min(low[u], dfn[v]);
33 }
34 }
35
36 }
37
38 int main() {
39 while (scanf("%d%d", &n, &m) != EOF && n) {
40 for (int i = 0; i < n; ++i) e[i].clear();
41 for (int i = 0; i < m; ++i) {
42 int u, v;
43 scanf("%d%d", &u, &v);
44 e[u].push_back(v);
45 e[v].push_back(u);
46 }
47 cut = 0;
48 for (int i = 0; i < n; ++i) {
49 del = i;
50 memset(dfn, 0, sizeof(dfn));
51 tot = 0;
52 root = !i;
53
54 Tarjan(root, -1);
55 if (cut) break;
56 for (int j = 0; j < n; ++j) {
57 if (j != del && !dfn[j]) { // 不是连通图
58 cut = 1;
59 break;
60 }
61 }
62 if (cut) break;
63 }
64 printf("%s
", cut ? "NO" : "YES");
65 }
66 return 0;
67 }