POJ 1144 Network【割顶】

学习的这一篇:https://www.byvoid.com/blog/biconnect

割顶:对于无向图G,如果删除某个点u后,连通分量数目增加,称u为图的关节点或者割顶

 

u为割顶的条件:

(1)u不为树根,以u的任一子节点为根的子树中没有一个点有返回u的祖先的反向边(返祖边)

(2)u为树根,且u有多于一个子树

紫书上有证明

即为,祖先与每一棵子树之间都有返祖边的话(即,删除u点之后,以v为根的整棵子树都可以通过这条返祖边连回到f),该点不是割顶,如果祖先与它的其中一棵子树缺少返祖边的话,那么这个点就是割顶

实现过程

(1)先链式前向星建图

(2)dfs

(3)定义dfn(u)为u在搜索中遍历到的序号      定义low(u)为u或u的子树能通过非父子边追溯到的最早的节点

  low(u)=min{dfn(u),       

                       dfn(v)//(u,v)为返祖边,等价于dfn(v)<dfn(u),且v不是u的父亲节点    

                       low(v)//(u,v)为树枝边(父子边)}

(4)当dfn(u)<=low(v)的时候,u为割顶

代码学习的这一篇

http://www.cnblogs.com/naturepengchen/articles/4053890.html

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring> 
 4 #include <cmath> 
 5 #include<stack>
 6 #include<vector>
 7 #include<map> 
 8 #include<set>
 9 #include<queue> 
10 #include<algorithm>  
11 using namespace std;
12 
13 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
14 
15 typedef long long LL;
16 const int INF = (1<<30)-1;
17 const int mod=1000000007;
18 const int maxn=100005;
19 
20 int first[maxn],next[maxn],ver[maxn];
21 int ecnt,tot;
22 int low[maxn],iscut[maxn],dfn[maxn];
23 
24 void dfs(int p,int pre){
25     low[p]=dfn[p]=++tot;
26     int son=0;
27     
28     for(int i=first[p];i!=-1;i=next[i]){
29         int v=ver[i];
30         if(!dfn[v]){
31             ++son;
32             dfs(v,p);
33             low[p]=min(low[p],low[v]);
34             if(low[v]>=dfn[p]) iscut[p]=1;
35         }
36         
37         else if(dfn[v]<dfn[p]&&v!=pre) {//用返祖边更新low函数 
38             low[p]=min(low[p],dfn[v]);
39         }
40     }
41     if(pre<0&&son==1) iscut[p]=0;     
42 }
43 
44 void addedges(int u,int v){
45     next[++ecnt]=first[u];
46     ver[ecnt]=v;
47     first[u]=ecnt;
48 }
49 
50 void init(){
51     memset(low,0,sizeof(low));
52     memset(dfn,0,sizeof(dfn));
53     memset(iscut,0,sizeof(iscut));
54     memset(first,-1,sizeof(first));
55     
56     ecnt=0;tot=0;
57 }
58 
59 int main(){
60     int a,b,n;
61     char c;
62     while(scanf("%d",&n)!=EOF&&n){
63         init();
64         while(scanf("%d",&a)!=EOF&&a){
65             while(scanf("%d%c",&b,&c)!=EOF){
66                 addedges(a,b);
67                 addedges(b,a);
68                 if(c=='\n') break;
69             }
70         }
71         dfs(1,-1);
72         int ans=0;
73         for(int i=1;i<=n;i++)
74         ans+=iscut[i];
75         
76         printf("%d\n",ans);
77     }
78     return 0;
79 }
View Code

 

转载于:https://www.cnblogs.com/wuyuewoniu/p/4473435.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值