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;
}
posted @ 2026-04-21 17:41  alice_ss  阅读(7)  评论(0)    收藏  举报
//雪花飘落效果