【POJ1523】SPF 不太单纯的无向图求割点啦啦啦

无向图割点的求法可以详见下一篇博文(包您满意)

题目大意:给定一个连通网络,网络的结点数<=1000,求出这个网络的所有割点编号,并求出若删去其中一个割点k后,对应的,原网络会被分割为多少个连通分量?

题目解析:前一部分是单纯求割点,而后一部分就要使成为割点的子节点数+1就行(还有父辈们一个),注意root不能加1哦(需要注意输出格式!)

代码如下:

#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int time,n,m,x,y,ans,top,j,ans1,ans2,root,tot;
int next[40005],to[40005],head[50001],dfn[50001],low[50001];
int in[50001],cut[50001],stack[40005],belong[40005],check[40005];
int zz[40005],ds[400005];
void add(int x,int y)
{
    tot++;
    next[tot]=head[x];
    to[tot]=y;
    head[x]=tot;
}
void dfs(int u,int fa)
{
    int i;
    if (fa!=-1)
    {
        ds[u]++;
    }
    in[u]=1;
    stack[++top]=u;
    low[u]=dfn[u]=++time;
    int ok=0,son=0;
    for(int i=head[u];i;i=next[i])
    {
        int v=to[i];
        if (v==fa&&ok==0) 
        {
            ok=1;
            continue;
        }
        if (dfn[v]==0)
        {
            son++;
            dfs(v,u);
            if (low[v]>=dfn[u])
            {
                cut[u]=1;
                ds[u]++;
            }
            if (low[v]>dfn[u]) ans2++;
            low[u]=min(low[u],low[v]);
        }
        else if (in[v]==1)
        {
            low[u]=min(low[u],dfn[v]);
        }

    }
    if (u==root)
    {
        if (son>1) cut[u]=1;
        else cut[u]=0;
    }
    if(dfn[u]==low[u])
    {
        int hh;
        do
        {
            hh=stack[top--];
            belong[hh]=ans;
            check[ans]++;
            in[hh]=0;
        }while(hh!=u);
        ans++;
    }
}
void hhhh()
{
    memset(next,0,sizeof(next));
    memset(to,0,sizeof(to));
    memset(belong,0,sizeof(belong));
    memset(check,0,sizeof(check));
    memset(in,0,sizeof(in));
    memset(head,0,sizeof(head));
    memset(zz,0,sizeof(zz));
    memset(ds,0,sizeof(ds));
    memset(cut,0,sizeof(cut));
    memset(belong,0,sizeof(belong));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(stack,0,sizeof(stack));
    time=n=m=x=y=ans=top=j=ans1=ans2=root=tot=0;
}
int main()
{
    int a;
    scanf("%d",&a);
    int kk=1;
    while(a)
    {

        hhhh();
        n=max(n,a);
        scanf("%d",&m);
        n=max(n,m);
        add(a,m);
        add(m,a);
        scanf("%d",&x);
        while(x)
        {
            n=max(n,x);
            scanf("%d",&y);
            n=max(n,y);
            add(x,y);
            add(y,x);
            scanf("%d",&x);
        }
        for(int i=1;i<=n;i++)
        {
            if (dfn[i]==0) 
            {
                root=i;
                dfs(i,-1);
            }
        }
        /*for(int i=1;i<=n;i++)
        {
            printf("%d ",belong[i]);
        }
        printf("\n");
        /*for(int i=0;i<ans;i++)
        {
            printf("%d ",come[i]);
        }*/
        printf("Network #%d\n",kk++);
        for(int i=1;i<=n;i++)
            if (cut[i]) ans1++;
        if(ans1==0)
        {
            printf("  No SPF nodes\n\n");
            scanf("%d",&a);
            continue;
        }
        int k=0;
        for(int i=1;i<=n;i++)
            if (cut[i])
            {
                zz[k++]=i;
            }
        sort(zz,zz+k);
        for(int i=0;i<k;i++)
        {
            printf("  SPF node %d leaves %d subnets\n",zz[i],ds[zz[i]]);
        }
        printf("\n");
        scanf("%d",&a);
    }
    return 0;
}

好了如果还有什么不懂的,可以给博主留言,或者直接加博主qq1067311025询问博主,不过博主可能是个蒟蒻,很菜。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值