码迷,mamicode.com
首页 > 其他好文 > 详细

POJ1523 SPF【割点】【Tarjan】

时间:2015-02-17 15:22:03      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

http://poj.org/problem?id=1523


题目大意:

有一个网络,在这个网络里,电脑之间的通信只能是两台电脑间(点对点)双向通信。如下面左图

所示:如果3号电脑出故障了,那么1号和2号之间、4号和5号之间还可以通信,不过1、2和3、4

号电脑之间就不能通信了,那么3号电脑就是一个SPF节点,且3号电脑故障后,整个网络被分为

了2个子网络。那么问题来了:给你一些边。问删除某个SPF节点后,可以将图分为几个连通分量。

技术分享


思路:

其实就是给你一个连通图,求出这个连通图的所有割点编号,并求出若删去其中一个割点后,原网

络被分成几个子网络。这里我们使用的思路和Tarjan算法类似。

(1)对原图进行深度优先搜索,计算树上每一个节点v的搜索深度标号dfn[v]。

(2)计算所有节点v的low[v]是在深度优先搜索树上按照后根遍历的顺序进行的。所以,当访问节点v

时它的儿子u的low[u]已经计算完毕,这时low[v]取下面三个值中的最小值。1.dfn[v]、2.dfn[w](凡

是含有回退边(v,w)的任何节点w)、3.low[u](对v的任何儿子u)

(3)然后判断一个点是不是割点,如果一个节点v是割点,满足下面两种情况。

1.v为树根,且v有多于一个子树;2.v不为树根,且满足存在边(v,u),使得dfn[v] <= low[u]。

注:我在程序中定义son[v]为节点v的深度,深度优先搜索时,每入栈一次,son[v]+1,每退栈一次,

son[v]-1。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 1010;
const int MAXM = MAXN*MAXN;

struct EdgeNode
{
    int to;
    int next;
}Edges[MAXM];
int Head[MAXN];

int dfn[MAXN],low[MAXN],Stack[MAXN],son[MAXN];
int m,id,scc,lay,N;

void AddEdges(int u,int v)
{
    Edges[id].to = v;
    Edges[id].next = Head[u];
    Head[u] = id++;
}

void TarjanBFS(int pos,int from)
{
    Stack[m++] = pos;
    dfn[pos] = low[pos] = ++lay;
    for(int i = Head[pos]; i != -1; i = Edges[i].next)
    {
        if(Edges[i].to == from)
            continue;
        if( !dfn[Edges[i].to])
        {
            TarjanBFS(Edges[i].to,pos);
            low[pos] = min(low[pos],low[Edges[i].to]);
            if( dfn[pos] <= low[Edges[i].to] )
            {
                while(Stack[m--] != Edges[i].to);
                son[pos]++;
            }
        }
        else
            low[pos] = min(low[pos],low[Edges[i].to]);
    }
}

int main()
{
    int u,v,kase = 0;
    while(~scanf("%d",&u) && u)
    {
        N = -1;
        m = lay = scc = id = 0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(son,0,sizeof(son));
        memset(Head,-1,sizeof(Head));
        N = max(N,u);
        scanf("%d",&v);
        N = max(N,v);
        AddEdges(u,v);
        AddEdges(v,u);
        while(scanf("%d",&u) && u)
        {
            N = max(N,u);
            scanf("%d",&v);
            N = max(N,v);
            AddEdges(u,v);
            AddEdges(v,u);
        }

        printf("Network #%d\n",++kase);
        TarjanBFS(1,0);
        son[1]--;
        int flag = 0;
        for(int i = 1; i <= N; ++i)
        {
            if(son[i] > 0)
            {
                printf("  SPF node %d leaves %d subnets\n", i, son[i]+1);
                flag = 1;
            }
        }
        if(flag == 0)
            printf("  No SPF nodes\n");
        printf("\n");

    }

    return 0;
}


POJ1523 SPF【割点】【Tarjan】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/43865313

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!