loj 1063(求割点个数)

来源:互联网 发布:声学模拟软件 编辑:程序博客网 时间:2024/05/22 00:29

题目链接: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

 

0 0
原创粉丝点击