割点

来源:互联网 发布:山东移动便利店软件 编辑:程序博客网 时间: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
原创粉丝点击