求割点详解 以poj1523为例

一、概念

         割点(关节点)

         生成树的边,回边,交叉边

Dfn[]:深度优先数,根节点为1

Low[u]:从u或u的子孙出发童工回边可以到达的最低深度优先数,求法:

low[u]=Min{dfn[u],Min{low[w]|wu的一个子女},Min{dfn[v]|vu邻接,(u,v)是一条回边}}

区分wu的子女还是(w,u)是回边的方法:dfs的时候,若与当前u邻接的点w已经被访问过,则(w,u)是回边,否则w是u的子女

二、定理

         u是关节点的重要条件:

         (1)若u是深度优先搜索树的根,u至少有两个子女

                   原因很容易理解

         (2)若u不是生成树的根,它至少有一个子女w,从w出发不可能通过w、w的子孙以及一条回边组成的路径到达u的祖先(用low[]理解,就是等价于low[w]>=dfn[u])

                   证明:反证

         重要的条件的另一种叙述方式:

         U或者是具有两个以上子女的深度优先生成树的根,或者虽然不是一个根,但它有一个子女w,使得low[w]>=dfn[u]

 

去掉关节点之后原来的连通图分成了几个连通分量:

(1)若u是根结点,则有几个子女,就分成了几个连通分量

(2)若关节点u不是根结点,则有d个子女w,使得low[w]>=dfn[u],则去掉该结点,分成了d+1个连通分量

附例题:
poj 1523

SPF

Time Limit: 1000MS

Memory Limit: 10000K

Total Submissions: 4906

Accepted: 2260

Description

Consider the twonetworks shown below. Assuming that data moves around these networks onlybetween directly connected nodes on a peer-to-peer basis, a failure of a singlenode, 3, in the network on the left would prevent some of the still availablenodes from communicating with each other. Nodes 1 and 2 could still communicatewith each other as could nodes 4 and 5, but communication between any otherpairs of nodes would no longer be possible. 

Node 3 is therefore a Single Point of Failure (SPF) for this network. Strictly,an SPF will be defined as any node that, if unavailable, would prevent at leastone pair of available nodes from being able to communicate on what waspreviously a fully connected network. Note that the network on the right has nosuch node; there is no SPF in the network. At least two machines must failbefore there are any pairs of available nodes which cannot communicate. 

Input

The input willcontain the description of several networks. A network description will consistof pairs of integers, one pair per line, that identify connected nodes.Ordering of the pairs is irrelevant; 1 2 and 2 1 specify the same connection.All node numbers will range from 1 to 1000. A line containing a single zeroends the list of connected nodes. An empty network description flags the end ofthe input. Blank lines in the input file should be ignored.

Output

For each networkin the input, you will output its number in the file, followed by a list of anySPF nodes that exist. 

The first network in the file should be identified as "Network #1",the second as "Network #2", etc. For each SPF node, output a line,formatted as shown in the examples below, that identifies the node and thenumber of fully connected subnets that remain when that node fails. If thenetwork has no SPF nodes, simply output the text "No SPF nodes"instead of a list of SPF nodes.

Sample Input

1 2

5 4

3 1

3 2

3 4

3 5

0

 

1 2

2 3

3 4

4 5

5 1

0

 

1 2

2 3

3 4

4 6

6 3

2 5

5 1

0

 

0

Sample Output

Network #1

  SPF node 3 leaves 2 subnets

 

Network #2

  No SPF nodes

 

Network #3

  SPF node 2 leaves 2 subnets

  SPF node 3 leaves 2 subnets

Source

Greater New York2000

#include<cstdio>
#include<cstring>
using namespace std;
#define Max(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)
#define N 1002

int nodes,dfn[N],low[N],tmpdfn,subnet[N],son;
bool map[N][N],vis[N];

void dfs(int u)
{
    int i;

    dfn[u]=low[u]=tmpdfn;
    tmpdfn++;
    for(i=1;i<=nodes;i++)
    {
        if(map[u][i])
            if(!vis[i])
            {
                vis[i]=1;
                dfs(i);
                low[u]=Min(low[i],low[u]);
                if(low[i]>=dfn[u])
                {
                    if(u!=1)subnet[u]++;
                    if(u==1)son++;
                }
            }
            else
                low[u]=Min(low[u],dfn[i]);

    }
}

int main()
{
    //freopen("in.in","r",stdin);

    int i,j, u,v,find,number=1;

    while(1)
    {
        tmpdfn=1;
        son=find=nodes=0;
        memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        memset(subnet,0,sizeof(subnet));

        scanf("%d",&u);
        if(!u)break;
        scanf("%d",&v);
        nodes=Max(u,v);
        map[u][v]=map[v][u]=1;
        while(1)
        {
            scanf("%d",&u);
            if(!u)break;
            scanf("%d",&v);
            nodes=Max(nodes,v);
            nodes=Max(nodes,u);
            map[u][v]=map[v][u]=1;
        }
        vis[1]=1;/*这一句忘了最开始*/
        dfs(1);
        if(number>1)putchar('\n');
        printf("Network #%d\n",number++);
        //if(son>1)subnet[1]=son-1;/*这一句忘了*/
        //for(i=1;i<=nodes;i++)printf(" subnet[%d]=%d ",i,subnet[i]);
        for(i=1;i<=nodes;i++)
        {
            if(i==1)
               {
                   if(son>=2)printf("  SPF node 1 leaves %d subnets\n",son),find=1;
               }
            else
            {
                if(subnet[i])
                {
                    find=1;
                    printf("  SPF node %d leaves %d subnets\n",i,subnet[i]+1);
                }
            }
        }
        if(!find)printf("  No SPF nodes\n");
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值