题目背景
抗日战争时期,冀中平原的地道战曾发挥重要作用。
题目描述
地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
我们来定义一个危险系数 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(2≤n≤1000), m ( 0 ≤ m ≤ 2000 ) m(0 \le m \le 2000) m(0≤m≤2000),分别代表站点数,通道数。
接下来 m m m 行,每行两个整数 u , v ( 1 ≤ u , v ≤ n , u ≠ v ) u,v(1 \le u,v \le n,u\neq v) u,v(1≤u,v≤n,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;
}