loj 1063(求割点个数)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26780

思路:判断一个点是否是割点的两个条件:1、如果一个点v是根结点并且它的子女个数大于等于2,则v是割点。2、如果点v不是根结点,并且存在她的一个子女u,使得low[u]>=dfn[v],则v是割点。然后我发现以前求割点的写法有点问题,=.=//。幸好不是在比赛中遇到!贡献上最新模板。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define MAXN 44444
 7 
 8 struct Edge{
 9     int v,next;
10 }edge[MAXN<<1];
11 
12 int n,m,NE;
13 int head[MAXN];
14 
15 void Insert(int u,int v)
16 {
17     edge[NE].v=v;
18     edge[NE].next=head[u];
19     head[u]=NE++;
20 }
21 
22 int cnt,ans;
23 int low[MAXN],dfn[MAXN];
24 bool mark[MAXN];
25 
26 bool is_cutpoint[MAXN];
27 void Tarjan(int root,int u)
28 {
29     int rt_son=0;
30     low[u]=dfn[u]=++cnt;
31     mark[u]=true;
32     for(int i=head[u];i!=-1;i=edge[i].next){
33         int v=edge[i].v;
34         if(dfn[v]==0){
35             Tarjan(root,v);
36             low[u]=min(low[u],low[v]);
37             if(u!=root&&low[v]>=dfn[u])is_cutpoint[u]=true;
38             rt_son++;
39         }else if(mark[v]){
40             low[u]=min(low[u],dfn[v]);
41         }
42     }
43     if(u==root&&rt_son>=2){
44         is_cutpoint[u]=true;
45     }
46 }
47 
48 int main()
49 {
50     int _case,u,v,t=1;
51     scanf("%d",&_case);
52     while(_case--){
53         scanf("%d%d",&n,&m);
54         NE=0;
55         memset(head,-1,sizeof(head));
56         while(m--){
57             scanf("%d%d",&u,&v);
58             Insert(u,v);
59             Insert(v,u);
60         }
61         cnt=ans=0;
62         memset(mark,false,sizeof(mark));
63         memset(dfn,0,sizeof(dfn));
64         memset(is_cutpoint,false,sizeof(is_cutpoint));
65         for(int i=1;i<=n;i++){
66             if(dfn[i]==0)Tarjan(i,i);
67         }
68         for(int i=1;i<=n;i++)if(is_cutpoint[i])ans++;
69         printf("Case %d: %d
",t++,ans);
70     }
71     return 0;
72 }
View Code
原文地址:https://www.cnblogs.com/wally/p/3337663.html