题目地址:POJ 1523

这题猛的一看。。貌似有点难的样子。不过仔细一想,那个每个割点所分成一次子图不就都能找到这个割点一次吗,那么只要记录下它作为割点的次数再+1不就行了。也算是求割点的裸题吧。这个题的输出很坑。。。需要注意一下。。

代码如下:


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
int head[1100], cnt, index1, flag;
int low[1100], dfn[1100], ge[1100], vis[1100];
struct node
{
    int u, v, next;
}edge[100000];
void add(int u, int v)
{
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void tarjan(int u, int fa)
{
    low[u]=dfn[u]=++index1;
    vis[u]=1;
    int son=0, i;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        son++;
        if(!vis[v])
        {
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(u==1&&son>1||u!=1&&dfn[u]<=low[v])
            {
                ge[u]++;
                flag=1;
            }
        }
        else if(v!=fa)
            low[u]=min(low[u],dfn[v]);
    }
}
void init()
{
    memset(head,-1,sizeof(head));
    cnt=0;
    memset(dfn,0,sizeof(dfn));
    memset(vis,0,sizeof(vis));
    memset(ge,0,sizeof(ge));
    index1=0;
    flag=0;
}
int main()
{
    int u, v, i, j, num=0, n;
    while(scanf("%d",&u)!=EOF&&u)
    {
        num++;
        init();
        scanf("%d",&v);
        add(u,v);
        add(v,u);
        n=max(u,v);
        while(scanf("%d",&u)!=EOF&&u)
        {
            scanf("%d",&v);
            add(u,v);
            add(v,u);
            n=max(n,max(u,v));
        }
        tarjan(1,-1);
        printf("Network #%d\n",num);
        if(!flag)
        {
            printf("  No SPF nodes\n\n");
            continue ;
        }
        for(i=1;i<=n;i++)
        {
            if(ge[i])
            {
                printf("  SPF node %d leaves %d subnets\n",i,ge[i]+1);
            }
        }
        printf("\n");
    }
    return 0;
}