題目連接:http://poj.org/problem?id=1144html
題目大意:給以一個無向圖,求割點數量。ios
這道題目的輸入和咱們通常見到的不太同樣。
它首先輸入 \(N\)(\(\lt 100\))表示點的數量(\(N=0\)表示文件輸入結束)。
而後接下來每行輸入一組數字。測試
因此這道題目想要表達的意思仍是同樣的 \(\Rightarrow\) 求割點的數量,只不過輸入方式和咱們平時見到的不太同樣。spa
觀察DFS搜索樹,咱們能夠發現有兩類節點能夠成爲割點:code
實現代碼以下:htm
#include <iostream> #include <string> #include <sstream> #include <vector> #include <cstdio> using namespace std; const int maxn = 10010; int n, m, dfn[maxn], low[maxn], f[maxn], cnt, ans; bool vis[maxn]; vector<int> g[maxn]; void init() { ans = cnt = 0; for (int i = 1; i <= n; i ++) { low[i] = dfn[i] = f[i] = vis[i] = 0; g[i].clear(); } } void tarjan(int u) { low[u] = dfn[u] = ++cnt; int son_num = 0; // 記錄子樹數量 int sz = g[u].size(); for (int i = 0; i < sz; i ++) { int v = g[u][i]; if (!dfn[v]) { // v未被訪問,(u,v)爲樹邊 son_num ++; f[v] = u; tarjan(v); low[u] = min(low[u], low[v]); if (dfn[u] == 1 && son_num > 1 && !vis[u]) { // 根節點,子樹數量大於1即爲割點 vis[u] = true; ans ++; } else if (dfn[u] != 1 && low[v] >= dfn[u] && !vis[u]) { // 其他節點子樹可追溯到最先的祖先節點要麼爲v要麼爲u vis[u] = true; ans ++; } } else if (f[v] != u) { // 節點v已被訪問,則(u,v)爲回邊 low[u] = min(low[u], dfn[v]); } } } int main() { while (~scanf("%d", &n) && n) { init(); getchar(); string s; int a, b; while (getline(cin, s)) { stringstream ss(s); ss >> a; if (!a) break; while ((ss >> b) && b) { g[a].push_back(b); g[b].push_back(a); } } tarjan(1); cout << ans << endl; } return 0; }
參考連接:blog