POJ1523 SPF (求割点)

6 篇文章 0 订阅

传送门
题目大意:求出每一个割点能将图分成几个部分。

思路:乱搞O(∩_∩)O(遇见割点,在对应的数组里加1就行了),但是要注意输出格式很坑,每次要多输出一个空行。

#include<cstdio>
#include<cstring>
#define min(a,b) (a)<(b)?(a):(b)
#define MAXN 5005
#define MAXM 20005
struct node
{
    int v;
    node *next;
} Edge[MAXM], *Adj[MAXN], *Mcnt = Edge;
void addedge(int u, int v)
{
    node *t = ++Mcnt;
    t->v = v;
    t->next = Adj[u];
    Adj[u] = t;
}
int dfn[MAXN], low[MAXN], cnt, rtson;
int isc[MAXN]; // 表示去掉某个点能将图分成几部分
void dfs(int u, int fa)
{
    dfn[u] = low[u] = ++cnt;
    int son = 0;
    for(node *p = Adj[u]; p; p = p->next)
    {
        if(!dfn[p->v])
        {
            dfs(p->v, u);
            low[u] = min(low[u],low[p->v]);
            if(low[p->v] >= dfn[u] && fa != -1) ++isc[u];
            son++;
        }
        else if(p->v != fa)low[u] = min(low[u], dfn[p->v]);
    }
    if(fa == -1 && son > 1) rtson = son;
}
int main()
{
    int t1, t2;
    int Cas = 0;
    while(~scanf("%d", &t1))
    {
        ++Cas;
        if(t1 == 0)return 0;
        scanf("%d", &t2);
        memset(Adj, 0, sizeof Adj);
        memset(isc, 0, sizeof isc);
        memset(dfn, 0, sizeof dfn);
        memset(low, 0, sizeof low);
        Mcnt = Edge;
        cnt = 0;
        rtson = 0;
        addedge(t1, t2);
        addedge(t2, t1);
        while(~scanf("%d", &t1))
        {
            if(t1 == 0) break;
            scanf("%d", &t2);
            addedge(t1, t2);
            addedge(t2, t1);
        }
        dfs(1, -1);
        bool flag = 1;
        printf("Network #%d\n",Cas);
        if(rtson>1) isc[1] = rtson;
        for(int i = 1; i <= cnt; i++)
            if(isc[i])
            {
                printf("  SPF node %d leaves %d subnets\n", i, isc[i] + (i != 1)); //因为若不是根节点,除了能分出几个子树外,还留下了一块
                flag = 0;
            }
        if(flag)
            puts("  No SPF nodes");
        putchar('\n');
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值