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是割点。然后我发现以前求割点的写法有点问题,=.=//。幸好不是在比赛中遇到!贡献上最新模板。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }