P1700 [USACO19OPEN] Milk Factory B

题目描述

牛奶生意正红红火火!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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值