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\n", cut ? "NO" : "YES"); 65 } 66 return 0; 67 }