割点
来源:互联网 发布:山东移动便利店软件 编辑:程序博客网 时间:2024/05/01 08:59
割点就是缺失这个点后,联通分支增加。
/*sample in55 1 2 3 4062 1 35 4 6 200sample out12*/#include<stdio.h>#include <string.h>#define Max 0x7fffffffint n,vis[100],pre[100],low[100],kids[100],cute[100],map[100][100];//pre时用pre(u)记录u的访问时间,//用low(u)数组记录u和u的子孙能追溯到的最早的节点(dfn值最小)。//顶点u是割点当且仅当其满足(1)或者(2)://(1) 若u是树根,且u的孩子数kids>1。因为没有u后,以这些孩子为根的子树间互相就不连通了,所以去掉u后得到kids个分支。//(2) 若u不是树根,且存在树边(u,v)使 low(v)>=pre(u)。low值说明以v为根的子树不能到达u的祖先也就是去掉u后不能和原图联通,所以得到{这样的v的个数+1}个分支。int min(int a,int b){ return a>b?b:a;}void dfs(int k,int deep){ int i; pre[k]=low[k]=deep; vis[k]=1; for(i=1; i<=n; i++) { if(map[k][i]==1) { if(vis[i]==1) { low[k]=min(low[k],pre[i]); } else { kids[k]++; dfs(i,deep+1); low[k]=min(low[k],low[i]); if(k==1&&kids[k]>1) { cute[k]=1; } else if(k!=1&&low[i]>=pre[k]) cute[k]=1; } } }}int main(){ int i,m,temp,sum; char c; while(scanf("%d",&n),n) { memset(vis,0,sizeof(vis)); memset(pre,0,sizeof(pre)); memset(kids,0,sizeof(kids)); memset(map,0,sizeof(map)); memset(cute,0,sizeof(cute)); for(i=0; i<100; i++) low[i]=Max; scanf("%d",&m); while(m!=0) { while((c=getchar())!='\n') { scanf("%d",&temp); map[m][temp]=map[temp][m]=1; } scanf("%d",&m); } dfs(1,1); sum=0; for(i=0; i<100; i++) if(cute[i])sum++; printf("%d\n",sum); } return 0;}
0 0