SPF poj 1523(强连通分量+割点)

原题目:

Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a failure of a single node, 3, in the network on the left would prevent some of the still available nodes from communicating with each other. Nodes 1 and 2 could still communicate with each other as could nodes 4 and 5, but communication between any other pairs 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 least one pair of available nodes from being able to communicate on what was previously a fully connected network. Note that the network on the right has no such node; there is no SPF in the network. At least two machines must fail before there are any pairs of available nodes which cannot communicate.

Input

The input will contain the description of several networks. A network description will consist of 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 zero ends the list of connected nodes. An empty network description flags the end of the input. Blank lines in the input file should be ignored.

Output

For each network in the input, you will output its number in the file, followed by a list of any SPF 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 the number of fully connected subnets that remain when that node fails. If the network 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

中文概要:

拿左边的图举例,有一个网络,在这个网络只能是点对点通信,如果3号节点出故障了,那么1号节点与2号节点,4号节点和5号节点还是可以通信的,不过1,2号不能和4,5号节点通信了。这样3号节点就是一个SPF节点,并且当3号节点出故障了分为了2个子网络
差不多就是说与许多点,有些点之间有无向边,问删除某个点之后,可以将图分为几块


/*

Memory 1172K

Time    16MS 

*/

#include <iostream>

using namespace std;

#define MAXV 1010

#define min(a,b) (a>b?b:a)

 

bool map[MAXV][MAXV];		//保存图

int rcnt;					//记录输入的结点

int dfn[MAXV],low[MAXV];	//深度与最低深度优先数

bool vis[MAXV];				//标记结点是否被寻找

int son;					//树根的子女结点的个数

int subnets[MAXV];			//记录删除i点后的连通分量

int count;					//记录访问

 

void init(){

	memset(dfn,0,sizeof(dfn));

	memset(low,0,sizeof(low));

	memset(vis,0,sizeof(vis));

	memset(subnets,0,sizeof(subnets));

	son=0;

	count=1;

	dfn[1]=low[1]=1;	//对根节点初始化

	vis[1]=1;

}

 

void dfs(int x){			//tajrjan

	for(int i=1;i<=rcnt;i++){

		if(map[x][i]){

			if(!vis[i]){

				vis[i]=1;

				dfn[i]=low[i]=++count;

				dfs(i);

				low[x]=min(low[x],low[i]);

				if(low[i]>=dfn[x]){

					if(x!=1) subnets[x]++;

					if(x==1) son++;

				}

			}else low[x]=min(low[x],dfn[i]);

		}

	}

}

 

void work(){

	init();

	dfs(1);

}

void Output(){

	int flag=0;

	if (son>1) subnets[1]=son-1;			//到时候输出要+1

	for(int i=1;i<=rcnt;i++){

		if(subnets[i]){

			printf("  SPF node %d leaves %d subnets\n",i,subnets[i]+1);

			flag=1;

		}

	}

	if(!flag) printf("  No SPF nodes\n");

		printf("\n");

}

 

void cntv(int x){

	rcnt=(rcnt>x?rcnt:x);

}

 

int main(){

//	freopen("d:\\test.in","r",stdin);

	int a,b,Case=0;

	while(scanf("%d",&a) && a){

		memset(map,0,sizeof(map));

		scanf("%d",&b);

		map[a][b]=map[b][a]=1;

		rcnt=0;

		cntv(a),cntv(b);

		while(scanf("%d",&a) && a){

			scanf("%d",&b);

			map[a][b]=map[b][a]=1;

			cntv(a),cntv(b);

		}

		work();

		printf("Network #%d\n",++Case);

		Output();

	}

	return 0;

}

思路:

就是求关节点。(去掉使得图不联通的点)

一个裸的求割点的题目,割点的定义是,在一个连通图,删除某一个点之后,这个图不再连通,那么称这个点为割点,又可以叫关节点,而分为几块的意思是求删除这个点之后有多少个连通分量
一个暴力算法是,将每个点删除之后求连通分量再恢复这个点,但是时间复杂度是O(n^3)
但是根据定理用tarjan算法可以以O(n^2)的时间复杂度求出:
点x是关节点的充分必要条件是
1.x是深搜的生成树的树根,那么如果x有2个以上的孩子结点,那么x是割点,并且连通分量就是孩子结点的数目
2.x不是树根,那么如果x有一个孩子结点,使得dfn[x]<=low[y],那么x也是一个割点,连通分量就是,看有多少个孩子
结点的符合这个条件,连通分量=符合条件的孩子数目+1
注:dfn代表深搜的先后顺序,low代表最低深度优先数,
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

deebcjrb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值