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\n",t++,ans);

70     }

71     return 0;

72 }
View Code

 

你可能感兴趣的:(OJ)