2026.04.20作业 - # AtCoder Beginner Contest 454 C -Straw Millionaire
问题陈述
有 \(N\) 种物品,编号为 \(1\) 到 \(N\)。最初,高桥只拥有物品 \(1\)。
他有 \(M\) 个朋友。对于第 \(i\) 个朋友,如果高桥把物品 \(A_i\) 送给这位朋友,他就会收到物品 \(B_i\)。
请问,高桥最终能够获得的物品种类有多少种?包括最初拥有的物品 \(1\)。
输入格式
输入通过标准输入给出,格式如下:
N M
A_1 B_1
A_2 B_2
...
A_M B_M
约束条件
- \(1 \leq N, M \leq 3 \times 10^5\)
- \(1 \leq A_i, B_i \leq N\)
- 输入中的所有值均为整数。
输出格式
输出一个整数,表示高桥能够获得的物品种类数。
示例
样例 1
输入
5 4
1 2
1 3
2 4
3 5
输出
5
解释:高桥可以从物品 \(1\) 交换得到物品 \(2\) 和 \(3\),再进一步交换得到物品 \(4\) 和 \(5\),因此他最终可以获得所有 \(5\) 种物品。
样例 2
输入
3 2
1 2
2 1
输出
2
解释:高桥只能在物品 \(1\) 和 \(2\) 之间反复交换,无法获得物品 \(3\)。
算法分析
- 思考 : \(M\) 位朋友,只是用来实现 \(M\) 次交易。本质是 物品 \(A_i\) 与物品 \(B_i\) 存在一条有向边。
- 本质是求从 1 出发,可以到达点的数量。
#include <bits/stdc++.h>
#define MaxN 300004
using namespace std;
int n, m, Ans;
bool F[MaxN];
vector<int> G[MaxN]; // 存图:G[a] 存储所有 a 可以交换到的物品(有向边)
// DFS函数:从当前物品k出发,遍历所有能交换到的物品
void dfs(int k) {
F[k] = 1; // 标记当前物品k已经获得
Ans++; // 获得新物品,答案+1
// 遍历k能交换到的所有物品e
for (int e : G[k]) {
if (!F[e]) { // 如果e还没获得过
dfs(e);
}
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int a, b;
scanf("%d%d", &a, &b);
G[a].push_back(b);
}
dfs(1);
cout << Ans << endl;
return 0;
}

浙公网安备 33010602011771号