著名的王牌间谍 007 需要执行一次任务,获取敌方的机密情报。已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门。每一扇门背后或者是一个房间,或者又有很多条路,同样是每条路通向一扇门…… 他的手里有一张表格,是其他间谍帮他收集到的情报,他们记下了每扇门的编号,以及这扇门背后的每一条通路所到达的门的编号。007 发现不存在两条路通向同一扇门。
内线告诉他,情报就藏在迷宫的最深处。但是这个迷宫太大了,他需要你的帮助 —— 请编程帮他找出距离入口最远的那扇门。
输入格式:
输入首先在一行中给出正整数 N(<105),是门的数量。最后 N 行,第 i 行(1≤i≤N)按以下格式描述编号为 i 的那扇门背后能通向的门:
K D[1] D[2] ... D[K]
其中 K
是通道的数量,其后是每扇门的编号。
输出格式:
在一行中输出距离入口最远的那扇门的编号。题目保证这样的结果是唯一的。
输入样例:
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
输出样例:
12
在主程序中构造有向图
vector<vector<int>> graph(N + 1);
for (int i = 1; i <= N; ++i) {
int K;
cin >> K;
for (int j = 0; j < K; ++j) {
int neighbor;
cin >> neighbor;
graph[i].push_back(neighbor);
// 添加反向边,因为每个门都是有向的
graph[neighbor].push_back(i);
}
}
通过输入构建了一个有向图,使用邻接表的形式表示。同时,为了实现有向图的深度搜索,对于每条有向边 (i, neighbor)
,也添加了反向边 (neighbor, i)
。
深度搜索
int deepestDoor = 0;
int deepestDepth = 0;
vector<bool> visited(N + 1, false);
// 从任意门开始进行深度优先搜索
for (int i = 1; i <= N; ++i) {
if (!visited[i]) {
findDeepestDoor(graph, i, visited, deepestDoor, deepestDepth);
}
}
使用深度优先搜索遍历图,找到最深的门的编号和深度。
输出结果:
cout << deepestDoor << endl;
输出找到的最深的门的编号。
总体来说,这个程序的目标是找到有向图中的最深的门,并输出其编号。这是通过深度优先搜索实现的,遍历了所有可能的起始门,找到深度最大的那个门。
最重要的是findDeepestDoor函数
void findDeepestDoor(const vector<vector<int>>& graph, int start, vector<bool>& visited, int& deepestDoor, int& deepestDepth) {
// 函数实现
}
void findDeepestDoor(const vector<vector<int>>& graph, int start, vector<bool>& visited, int& deepestDoor, int& deepestDepth) {
stack<pair<int, int>> s; // 使用栈来进行深度优先搜索,每个元素包括门的编号和当前深度
s.push({start, 0});
while (!s.empty()) {
int current = s.top().first;
int depth = s.top().second;
s.pop();
visited[current] = true;
// 更新最深的门的信息
if (depth > deepestDepth) {
deepestDoor = current;
deepestDepth = depth;
}
for (int neighbor : graph[current]) {
if (!visited[neighbor]) {
s.push({neighbor, depth + 1});
}
}
}
}
这是一个用于深度优先搜索(DFS)的函数,目的是找到最深的门。现在详细解释其各部分:
-
输入参数:
graph
:表示有向图的邻接表。start
:表示深度优先搜索的起始门的编号。visited
:用于记录哪些门已经被访问过的布尔向量。deepestDoor
:用于记录最深门的编号。deepestDepth
:用于记录最深门的深度。
-
算法流程:
- 使用栈
s
来实现深度优先搜索。 - 将起始门
start
和深度0
入栈。 - 进入循环,直到栈为空。
- 弹出栈顶元素,得到当前门的编号
current
和深度depth
。 - 将当前门标记为已访问。
- 如果当前深度比已记录的最深深度
deepestDepth
大,则更新deepestDoor
和deepestDepth
。 - 遍历当前门的邻居,如果邻居未被访问,则将邻居和深度加一的信息入栈。
- 继续循环,直到栈为空。
- 使用栈
-
最终结果:
- 函数执行完毕后,
deepestDoor
中存储的是最深门的编号,deepestDepth
中存储的是最深门的深度。
- 函数执行完毕后,
这个函数的主要作用是在给定有向图中从指定门开始进行深度优先搜索,找到最深的门并记录其编号和深度。
答案:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
void findDeepestDoor(const vector<vector<int>>& graph, int start, vector<bool>& visited, int& deepestDoor, int& deepestDepth) {
stack<pair<int, int>> s; // 使用栈来进行深度优先搜索,每个元素包括门的编号和当前深度
s.push({start, 0});
while (!s.empty()) {
int current = s.top().first;
int depth = s.top().second;
s.pop();
visited[current] = true;
// 更新最深的门的信息
if (depth > deepestDepth) {
deepestDoor = current;
deepestDepth = depth;
}
for (int neighbor : graph[current]) {
if (!visited[neighbor]) {
s.push({neighbor, depth + 1});
}
}
}
}
int main() {
int N;
cin >> N;
if (N == 1) {
// 如果只有一个门,直接输出这个门的编号
cout << 1 << endl;
return 0;
}
vector<vector<int>> graph(N + 1);
for (int i = 1; i <= N; ++i) {
int K;
cin >> K;
for (int j = 0; j < K; ++j) {
int neighbor;
cin >> neighbor;
graph[i].push_back(neighbor);
// 添加反向边,因为每个门都是有向的
graph[neighbor].push_back(i);
}
}
int deepestDoor = 0;
int deepestDepth = 0;
vector<bool> visited(N + 1, false);
// 从任意门开始进行深度优先搜索
for (int i = 1; i <= N; ++i) {
if (!visited[i]) {
findDeepestDoor(graph, i, visited, deepestDoor, deepestDepth);
}
}
// 输出结果
cout << deepestDoor << endl;
return 0;
}