一、概念
割点(关节点)
生成树的边,回边,交叉边
Dfn[]:深度优先数,根节点为1
Low[u]:从u或u的子孙出发童工回边可以到达的最低深度优先数,求法:
low[u]=Min{dfn[u],Min{low[w]|w是u的一个子女},Min{dfn[v]|v与u邻接,且(u,v)是一条回边}}
区分w是u的子女还是(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
#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;
}