POJ 1523 SPF【双连通分量_割点】

题意: 找出无向图的割点,并判断每个割点去掉后能形成多少个双连通分量。

分析: 割点的定义:

           在深搜树中,时间戳为 dfn[k] ,当 K 满足(1)(2)中一个时,k 为割点

     (1) k 为深搜树的根,当且仅当 k 的儿子个数>=2 时 k 为割点;

     (2) k 为深搜树的中间节点(k 既不是根也不是叶),那么k 必然有父亲和儿子;

      对于(1)是显然的,根结点k一旦有2个以上的分支,那么删除k必然出现森林;

      对于(2)首先注意low[son]>= dfn[k]这个条件,意思就是“k的儿子son的辈分最高的祖先(暂且设其为w)的深度,比k的深度要深(或者等于k的深度,此   时k就是w),就是说k的辈分比w更高(深度更浅),那么一旦删除k,son所在的网络势必和 k的father所在的网络断开”,那么k就是割点。

code :

#include<stdio.h>
#include<string.h>
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
const int maxn=1010;
struct node
{
    int to,next;
}e[10010];
int tot;
int head[maxn];
void add(int s,int u)
{
    e[tot].to=u;
    e[tot].next=head[s];
    head[s]=tot++;
}
int st,en;
int ti;
int dfn[maxn];
int low[maxn];
int num[maxn];
void dfs(int p,int u)
{
    dfn[u]=low[u]=++ti;
    int i,k;
    int son=0;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(k!=p&&dfn[k]>0)
            low[u]=min(low[u],dfn[k]);
        else if(dfn[k]==0)
        {
            son++;
            dfs(u,k);
            if(low[k]<low[u])
                low[u]=low[k];
            if((u==st&&son>=2)||(u!=st&&dfn[u]<=low[k]))
                num[u]++;
        }
    }
}
int main()
{
    int a,b,i;
    int ca=1;
    while(scanf("%d",&a),a)
    {
        scanf("%d",&b);
        ti=0;   tot=1;
        clr(head);
        st=1005;
        en=0;
        st=min(st,a);
        st=min(st,b);
        en=max(en,a);
        en=max(en,b);
        add(a,b);
        add(b,a);
        while(scanf("%d",&a),a)
        {
            scanf("%d",&b);
            st=min(st,a);
            st=min(st,b);
            en=max(en,a);
            en=max(en,b);
            add(a,b);
            add(b,a);
        }
        clr(dfn);   clr(low);
        clr(num);
        dfs(0,st);
        printf("Network #%d\n",ca++);
        bool flag=true;
        for(i=st;i<=en;i++)
            if(num[i])
            {
                flag=false;
                printf("  SPF node %d leaves %d subnets\n",i,num[i]+1);
            }
        if(flag)
        printf("  No SPF nodes\n");
        printf("\n");
    }
    return 0;
}


 

posted @ 2012-07-17 15:52  'wind  阅读(245)  评论(0编辑  收藏  举报