POJ 3713 Transferring Sylla【Tarjan求割点】

题意:给出一个无向图,判断是否任意两点间都存在至少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 }
原文地址:https://www.cnblogs.com/demian/p/9222257.html