題目連接:http://poj.org/problem?id=1144ios
觀察DFS搜索樹,咱們能夠發現有兩類節點能夠成爲割點:算法
#include<iostream> #include<vector> #include<cstdio> #include<string> #include<sstream> using namespace std; typedef long long ll; const int maxn=10005; vector<int> mp[maxn]; int n,m,ans,low[maxn],dfn[maxn],par[maxn],ap[maxn],cnt; void init(){ ans=0; cnt=0; for(int i=0;i<=n;i++){ low[i]=dfn[i]=0; par[i]=0; ap[i]=0; mp[i].clear(); } } void tarjan(int u){ dfn[u]=low[u]=++cnt; //cnt記錄遍歷次序 int son=0; //記錄子樹數量 for(int i=0;i<mp[u].size();i++){ int v=mp[u][i]; if(!dfn[v]){ //v未被訪問,(u,v)爲樹邊 son++; //記錄v的父親節點 par[v]=u; tarjan(v); low[u]=min(low[u],low[v]); //根節點,子樹數量大於1即爲割點 if(dfn[u]==1&&son>1&&!ap[u]) ap[u]=1,ans++; //其他節點子樹可追溯到最先的祖先節點要麼爲v要麼爲u else if(dfn[u]!=1&&low[v]>=dfn[u]&&!ap[u]) ap[u]=1,ans++; } else if(par[v]!=u) //節點v已被訪問,則(u,v)爲回邊 low[u]=min(low[u],dfn[v]); } } int main(){ int a,b; string s; while(~scanf("%d",&n)&&n){ init(); getchar(); while(1){ getline(cin,s); stringstream ss(s); ss>>a; if(!a)break; while(ss>>b&&b){ mp[a].push_back(b); mp[b].push_back(a); } } tarjan(1); cout<<ans<<endl; } return 0; }