题目描述
牛奶生意正红红火火!Farmer John 的牛奶加工厂内有 N 个加工站,编号为 1…N(1≤N≤100),以及 N−1 条通道,每条连接某两个加工站。(通道建设很昂贵,所以 Farmer John 选择使用了最小数量的通道,使得从每个加工站出发都可以到达所有其他加工站)。
为了创新和提升效率,Farmer John 在每条通道上安装了传送带。不幸的是,当他意识到传送带是单向的已经太晚了,现在每条通道只能沿着一个方向通行了!所以现在的情况不再是从每个加工站出发都能够到达其他加工站了。
然而,Farmer John 认为事情可能还不算完全失败,只要至少还存在一个加工站 i 满足从其他每个加工站出发都可以到达加工站 i。注意从其他任意一个加工站 j 前往加工站 i 可能会经过 i 和 j 之间的一些中间站点。请帮助 Farmer John 求出是否存在这样的加工站 i。
输入格式
输入的第一行包含一个整数 N,为加工站的数量。以下 N−1 行每行包含两个空格分隔的整数 ai 和 bi,满足 1≤ai,bi≤N 以及 ai=bi。这表示有一条从加工站 ai 向加工站 bi 移动的传送带,仅允许沿从 ai 到 bi 的方向移动。
输出格式
如果存在加工站 i 满足可以从任意其他加工站出发都可以到达加工站 i,输出最小的满足条件的 i。否则,输出 −1。
输入输出样例
输入 #1
3 1 2 3 2
输出 #1
2
#include<bits/stdc++.h>
using namespace std;
int n;
int u, v;
bool bk[110] = {}; // 用于标记节点是否被访问过
vector<vector<int>> e(110, vector<int>(110, 0));//邻接矩阵,e[i][j] = 1 表示从 i 到 j 有一条边
//从节点 y 出发,找到所有可以到达的节点
void dfs(int y) {
bk[y] = true; // 标记节点 y 被访问
for (int i = 1; i <= n; i++) {
if (e[i][y] && !bk[i]) { // 如果存在从 i 到 y 的边,并且 i 还没有被访问过
dfs(i); // 递归地从 i 开始搜索
}
}
}
int main() {
cin >> n; // 节点数量
//构建邻接矩阵
for (int i = 1; i < n; i++) {
cin >> u >> v;
e[u][v] = 1; // 标记
}
//遍历每个节点,检查是否所有其他节点都可以到达该节点
for (int i = 1; i <= n; i++) {
bool mark = false; // 标记是否存在不能到达节点 i 的节点
memset(bk, false, sizeof(bk));//重置标记
//从所有节点出发,尝试到达节点 i
for (int j = 1; j <= n; j++) {
if (e[j][i]) {//如果存在一条从 j 到 i 的边,则从 j 开始进行 dfs
dfs(j); // 从节点 j 开始搜索,标记所有可以从 j 到达的节点
}
}
//检查是否所有节点都被访问过
for (int j = 1; j <= n; j++) {
if (j == i) continue; // 跳过节点 i 本身
if (!bk[j]) mark = true; // 如果节点 j 没有被访问过,说明无法到达节点 i
}
//如果所有节点都可以到达节点 i
if (!mark) {
cout << i; // 输出节点 i 的编号
return 0;
}
}
cout << "-1"; // 如果没有找到,输出 -1
return 0;
}