著名的王牌间谍 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
第一种 dfs+回溯
因为只要最长分支的最后一个分支,只需通过dfs+回溯将最长分支存入数组中即可。
#include<bits/stdc++.h>
using namespace std;
vector<int>q;
vector<vector<int>>num;//存放输入数据
vector<int>q1;//存放最后结果的数组
int res;
//将最长分支存入数组中
void dfs(int i) {
if (num[i].size() == 0) {
if (q1.size() < q.size()) {
q1.clear();
q1 = q;
}
return;
}
for (int j = 0; j < num[i].size(); j++) {
q.emplace_back(num[i][j]);
dfs(num[i][j]);
q.pop_back();//回溯
}
}
int main() {
int n;
cin >> n;
vector<int>flag(n+1, 0);
for (int i = 0; i < n; i++) {
int a;
cin >> a;
vector<int>ans;
for (int j = 1; j <= a; j++) {
int b;
cin >> b;
flag[b] = 1;
ans.emplace_back(b);
}
num.emplace_back(ans);
}
num.insert(num.begin(), { 0 });
//通过标记找到根节点
for (int i = 1; i <= n; i++) {
if (flag[i] == 0) {
q.emplace_back(i);
res = i;
break;
}
}
dfs(res);//从根节点进行dfs
auto it = q1.end() - 1;
cout << *it;
return 0;
}
第二种 bfs+队列
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
queue<int>q;
vector<vector<int> >num;
vector<int>find(n + 1, 0);
for (int i = 1; i <= n; i++) {
vector<int>ans;
int a;
cin >> a;
ans.push_back(a);
for (int j = 1; j <= a; j++) {
int b;
cin >> b;
ans.push_back(b);
find[b] = 1;
}
num.push_back(ans);
}
num.insert(num.begin(), { 0 });
for (int i = 1; i <= n; i++) {
if (find[i] == 0) {
q.push(i);//将根节点放入队列
break;
}
}
int temp;
//通过广搜,一层一层的将数据放入队列,最后经过出队只剩下最深层的唯一一个元素
while (!q.empty()) {
temp = q.front();
q.pop();
for (int i = 1; i <= num[temp][0]; i++) {
q.push(num[temp][i]);
}
}
cout << temp;
return 0;
}