UVA 315 Network (模板题)(无向图求割点)

<题目链接>

题目大意:

给出一个无向图,求出其中的割点数量。

解题分析:

无向图求割点模板题。

一个顶点u是割点,当且仅当满足
(1) u为树根,且u有多于一个子树。
(2) u不为树根,且满足存在(u,v)为树枝边(或称 父子边,即u为v在搜索树中的父亲),使得 dfn(u)<=low(v)。(也就是说V没办法绕过 u 点到达比 u dfn要小的点)
注:这里所说的树是指,DFS下的搜索树。
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int M =1e4+10;
 6 int dfn[M],low[M],father[M],head[M];
 7 int n,m,tot,top,cnt;
 8 struct EDGE{
 9     int to,next;
10 }edge[M];
11 void init(){
12     memset(head,-1,sizeof(head));
13     memset(low,0,sizeof(low));
14     memset(dfn,0,sizeof(dfn));
15     memset(father,0,sizeof(father));
16     tot=cnt=0;
17 }
18 void add(int u,int v){
19     edge[++cnt].to=v,edge[cnt].next=head[u];
20     head[u]=cnt;
21 }
22 void Targan(int u,int fa){
23     dfn[u]=low[u]=++tot;
24     father[u]=fa;   //记录每个节点的父亲
25     for(int i=head[u];~i;i=edge[i].next){
26         int v=edge[i].to;
27         if(!dfn[v]){
28             Targan(v,u);
29             low[u]=min(low[u],low[v]);
30         }
31         else if(fa!=v){
32             low[u]=min(dfn[v],low[u]);
33         }
34     }
35 }
36 void solve(){
37     int rootson=0,ans=0;
38     bool cut[M]={false};   //标记该点是否为割点
39     Targan(1,-1);   //从1开始遍历整张图
40     for(int i=2;i<=n;i++){
41         int u=father[i];
42         if(u==1)rootson++;  //父亲为根节点,则根节点的分支+1
43         else if(dfn[u]<=low[i])cut[u]=true;   //说明i无法绕过它的父亲节点到达比dfn[u]更小的节点,说明u为割点 
44     }
45     for(int i=2;i<=n;i++){
46         if(cut[i])ans++;
47     }
48     if(rootson>1)ans++;   //如果根节点的子树数>1,则说明该根节点是割点
49     printf("%d
",ans);
50 }
51 int main(){
52     while(scanf("%d",&n)!=EOF,n){
53         init();
54         int u,v;
55         char ch;
56         while(scanf("%d",&u),u){
57             while(scanf("%d%c",&v,&ch)){
58                 add(u,v),add(v,u);
59                 if(ch=='
')break;
60             }
61         } 
62         solve();
63     }
64 }
 
 
 
2018-10-17
原文地址:https://www.cnblogs.com/00isok/p/9807964.html