[蓝桥杯 2013 国 C] 危险系数(图,DFS,C++)

题目背景

抗日战争时期,冀中平原的地道战曾发挥重要作用。

题目描述

地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。

我们来定义一个危险系数 D F ( x , y ) DF(x,y) DF(x,y)

对于两个站点 x x x y ( x ≠ y ) , y(x\neq y), y(x=y), 如果能找到一个站点 z z z,当 z z z 被敌人破坏后, x x x y y y 不连通,那么我们称 z z z 为关于 x , y x,y x,y 的关键点。相应的,对于任意一对站点 x x x y y y,危险系数 D F ( x , y ) DF(x,y) DF(x,y) 就表示为这两点之间的关键点个数。

本题的任务是:已知网络结构,求两站点之间的危险系数。

输入格式

输入数据第一行包含 2 2 2 个整数 n ( 2 ≤ n ≤ 1000 ) n(2 \le n \le 1000) n(2n1000) m ( 0 ≤ m ≤ 2000 ) m(0 \le m \le 2000) m(0m2000),分别代表站点数,通道数。

接下来 m m m 行,每行两个整数 u , v ( 1 ≤ u , v ≤ n , u ≠ v ) u,v(1 \le u,v \le n,u\neq v) u,v(1u,vn,u=v) 代表一条通道。

最后 1 1 1 行,两个数 u , v u,v u,v,代表询问两点之间的危险系数 D F ( u , v ) DF(u,v) DF(u,v)

输出格式

一个整数,如果询问的两点不连通则输出 − 1 -1 1

样例 #1

样例输入 #1

7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6

样例输出 #1

2

提示

时限 1 秒, 64M。蓝桥杯 2013 年第四届国赛

解题思路

本题的解题思路就是找出所有从u到v的路径,累计每个节点在路径中出现的次数,若二者相等,则该节点为关键节点

首先我们先利用vector实现存图的操作

#include <iostream>
using namespace std;

int n, m;//点数、边数
vector<int> nodes[max_n];//下标为点,两个下标确定一条有向边

int main()
{
	int temp_point_1, temp_point_2;
	cin >> n >> m;
	for (int i = 0; i < m; i++)//读入m条边
	{
		cin >> temp_point_1 >> temp_point_2;
		nodes[temp_point_1].push_back(temp_point_2);//从1到2
		nodes[temp_point_2].push_back(temp_point_1);//从2到1
	}
}

然后,既然要遍历每一条路径,那么我们采用深度优先搜索

void depth_first_search(int now)
{
	//终止条件
	if (now == ed)
	{
		path_sum++;//累计路径数
		for (int i = 1; i <= n; i++)//累计点出现的次数
		{
			if (book_nodes[i])
			{
				nodes_sum[i]++;
			}
		}
		return;
	}
	//递归主体
	for (int i = 0; i < int(nodes[now].size()); i++)//从now开始尝试每一个能到达的点
	{
		if (!book_nodes[nodes[now][i]])//如果未到达过
		{
			book_nodes[nodes[now][i]] = true;//标记
			depth_first_search(nodes[now][i]);
			book_nodes[nodes[now][i]] = false;//取消标记
		}
	}
	return;
}

本题基本实现完毕,完整的代码如下

#include <iostream>
#include <vector>
using namespace std;

const int max_n = 1000 + 1;

vector<int> nodes[max_n];
bool book_nodes[max_n] = { false };
int sta, ed, n, m;
int path_sum = 0;
int nodes_sum[max_n] = { 0 };

void depth_first_search(int now)
{
	//终止条件
	if (now == ed)
	{
		path_sum++;
		for (int i = 1; i <= n; i++)
		{
			if (book_nodes[i])
			{
				nodes_sum[i]++;
			}
		}
		return;
	}
	//递归主体
	for (int i = 0; i < int(nodes[now].size()); i++)
	{
		if (!book_nodes[nodes[now][i]])
		{
			book_nodes[nodes[now][i]] = true;
			depth_first_search(nodes[now][i]);
			book_nodes[nodes[now][i]] = false;
		}
	}
	return;
}

int main()
{
	int temp_point_1, temp_point_2, danger = 0;
	cin >> n >> m;
	for (int i = 0; i < m; i++)
	{
		cin >> temp_point_1 >> temp_point_2;
		nodes[temp_point_1].push_back(temp_point_2);
		nodes[temp_point_2].push_back(temp_point_1);
	}
	cin >> sta >> ed;
	book_nodes[sta] = true;//注意要标记起点
	depth_first_search(sta);
	book_nodes[sta] = false;
	if (path_sum != 0)//如果u,v之间连通
	{
		for (int i = 1; i <= n; i++)//统计关键节点数量
		{
			if (path_sum == nodes_sum[i])
			{
				danger++;
			}
		}
		cout << danger - 2 << endl;//减去起点和终点,输出
	}
	else
	{
		cout << -1 << endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WitheredSakura_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值