POJ1523——割点+连通分量

题目链接:

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 那样相互通信,但任何其他节点对之间的通信将不再可能。‎
‎因此,节点 3 是此网络的单点故障点 (SPF)。 ‎
‎严格来说,SPF 将定义为任何节点,如果不可用,将阻止至少一对可用节点在以前完全连接的网络上进行通信。请注意,右侧的网络没有此类节点;网络中没有 SPF。在有任何一对可用节点无法通信之前,必须至少两台计算机发生故障。‎

‎输入‎

‎输入将包含多个网络的说明。网络描述将由一对整数(每行一对)组成,用于标识连接的节点。对的顺序是无关紧要的;1 2 和 2 1 指定相同的连接。所有节点编号的范围为 1 到 1000。包含单个零的行将结束连接节点的列表。空网络描述标记输入的末尾。应忽略输入文件中的空白行。‎

‎输出‎

‎对于输入中的每个网络,您将在文件中输出其编号,后跟存在的任何 SPF 节点的列表。‎
‎文件中的第一个网络应标识为"网络#1",第二个网络应标识为"网络#2"‎
‎等。对于每个 SPF 节点,输出一行,格式如下示例所示,用于标识该节点和节点发生故障时保留的完全连接的子网数。如果网络没有 SPF 节点,只需输出文本"无 SPF 节点",而不是 SPF 节点列表。

 

题意很简单,就是让你求图中的割点个数有多少,之后再去求去掉割点后的连通分量的个数。

关于割点的求法不懂的可以看这篇文章:https://blog.csdn.net/wtyvhreal/article/details/43530613

求完割点后,再对每一个割点开始求DFS,利用刘汝佳白书里面的内容就可以求出连通分量的个数了。

an#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e3+7;
int low[maxn],dfn[maxn];
int visited[maxn];
int cut[maxn];
int head[maxn];
int n,num,kase,cnt,root,root_son,t;
struct Edge{
	int to,nxt;
}edge[maxn*100];
void init(){
	memset(head,-1,sizeof(head));
	memset(low,0,sizeof(low));
	memset(visited,0,sizeof(visited));
	memset(cut,0,sizeof(cut));
	memset(dfn,0,sizeof dfn);
	cnt=0;
	kase++;
	num=1;
	n=-1; 
}
void addedge(int from,int to){
	edge[cnt].to=to;
	edge[cnt].nxt=head[from];
	head[from]=cnt++;
}
void tarjan(int u){
	low[u]=dfn[u]=num++;
	for(int i = head[u];~i;i=edge[i].nxt){
		int v=edge[i].to;
		if(!dfn[v]){
			tarjan(v);
			if(u==root) root_son++;
			else {
				low[u]=min(low[u],low[v]);
				if(low[v]>=dfn[u]) cut[u]=1;
			}
		}
		else if(low[u]>dfn[v]) low[u]=dfn[v];
	}
}
void dfs(int u){
	visited[u]=1;
	for(int i = head[u];~i;i=edge[i].nxt){
		int v=edge[i].to;
		if(!visited[v]){
			visited[v]=1;
			dfs(v);
		}
	}
}
int main(int argc, char** argv) {
	kase=0;
	int u,v;
	while(~scanf("%d",&u)&&u){
		init();
		n=max(n,u);
		scanf("%d",&v);
		n=max(n,v);
		addedge(u,v);
		addedge(v,u);
		while(scanf("%d",&u)&&u){
			n=max(n,u);
			scanf("%d",&v);
			n=max(n,v);
			addedge(u,v);
			addedge(v,u);
		}
		root=1;
		root_son=0;
		tarjan(root);
		if(root_son>=2){
			cut[root]=1;
		}
		printf("Network #%d\n",kase);
		int flag=0;
		for(int u = 1;u<=n;++u){
			if(cut[u]){
				flag=1;
				memset(visited,0,sizeof(visited));
				visited[u]=1;
				int son=0;
				for(int i = head[u];~i;i=edge[i].nxt){
					int v=edge[i].to;
					if(!visited[v]){
						dfs(v);
						son++;
					}
				}
				printf("  SPF node %d leaves %d subnets\n",u,son);
			}
		}
		if(!flag) printf("  No SPF nodes\n");
		printf("\n");
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值