1. 程式人生 > >POJ 3713 Transferring Sylla【Tarjan求割點】

POJ 3713 Transferring Sylla【Tarjan求割點】

clu int 連通圖 memset wan tin con vector 編號

題意:給出一個無向圖,判斷是否任意兩點間都存在至少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 }

POJ 3713 Transferring Sylla【Tarjan求割點】