標籤:child get 個數 思路 沒有 min pre init 返回
來源:
Central Europe 1996
思路:
Tarjan求割點。
一個點$x$為割點若且唯若:
1.$x$為根結點且有兩棵不相交的子樹。
2.$x$不為根結點且它的子樹中沒有可以返回到$x$的祖先的邊。
實現細節:
當$x$為根結點時,不能單純地統計它的度,而是應該統計其不相交子樹的個數,因為如果剛好是一個環,每個點的度都是$2$,但去掉這個點以後還是連通的。
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 const int V=100; 5 const int root=1; 6 std::vector<int> e[V]; 7 inline void add_edge(const int u,const int v) { 8 e[u].push_back(v); 9 }10 int dfn[V],low[V],cnt;11 bool isCut[V];12 void Tarjan(const int x) {13 int child=0;14 dfn[x]=low[x]=++cnt;15 for(unsigned i=0;i<e[x].size();i++) {16 int &y=e[x][i];17 if(!dfn[y]) {18 Tarjan(y);19 low[x]=std::min(low[x],low[y]);20 child++;21 if(x!=root&&low[y]>=dfn[x]) isCut[x]=true;22 if(x==root&&child>1) isCut[x]=true;23 }24 else {25 low[x]=std::min(low[x],dfn[y]);26 }27 }28 }29 inline void init() {30 for(int i=0;i<V;i++) e[i].clear();31 memset(dfn,0,sizeof dfn);32 memset(low,0,sizeof low);33 memset(isCut,0,sizeof isCut);34 cnt=0;35 }36 int main() {37 for(;;) {38 int n;39 scanf("%d",&n);40 if(!n) return 0;41 init();42 for(;;) {43 int u;44 scanf("%d",&u);45 if(!u) break;46 while(getchar()!=‘\n‘) {47 int v;48 scanf("%d",&v);49 add_edge(u,v);50 add_edge(v,u);51 }52 }53 Tarjan(root);54 int ans=0;55 for(int i=1;i<=n;i++) {56 ans+=isCut[i];57 }58 printf("%d\n",ans);59 }60 }
[POJ1144]Network