1 条题解

  • 0
    @ 2025-6-22 14:33:36

    直接存所有边

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1000;
    int n, m;
    vector<pair<int, int>> e;
    bool vis[MAXN + 5]; // vis[i] 存从 1 能不能走到 i
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            e.push_back({u, v});
        }
        vis[1] = true;
        for (int i = 1; i <= n; i++)
            // for (auto &now : e) 也可以,且更快
            for (pair<int, int> now : e)
            {
                if (vis[now.first])
                    vis[now.second] = true;
            }
        int ans = 1;
        for (int i = 2; i <= n; i++)
            if (vis[i])
                ans = i;
        cout << ans;
        return 0;
    }
    

    邻接矩阵+广搜

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1000;
    int n, m;
    // e[i][j] 表示从 i 能否走到 j
    // O(n) 枚举某个起点的边,O(1) 判断两个点是否直接相连
    bool e[MAXN + 5][MAXN + 5];
    // 试试广搜
    queue<int> q;
    bool vis[MAXN + 5]; // vis[i] 存从 1 能不能走到 i
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            e[u][v] = true;
        }
        vis[1] = true;
        q.push(1);
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int v = 1; v <= n; v++)
            {
                if (e[u][v] && !vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
        int ans = 1;
        for (int i = 2; i <= n; i++)
            if (vis[i])
                ans = i;
        cout << ans;
        return 0;
    }
    

    邻接表+深搜

    显然邻接表也能广搜,邻接矩阵也能深搜,只有时间复杂度的区别。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1000;
    int n, m;
    // e[u] 存所有 u 为起点的边的终点
    // 均摊下来 m/n 的时间复杂度枚举某个起点的边
    // O(n) 判断 u,v 是否相连
    // 如果每个vector都排序了,就只要 logn(但是这样就不能新加边,否则要重新排序)
    // 如果要新加边,可以用 set<int> e[MAXN+5]; 达到比较快的速度
    vector<int> e[MAXN + 5];
    // 试试深搜
    bool vis[MAXN + 5]; // vis[i] 存从 1 能不能走到 i
    void dfs(int u)
    {
        vis[u] = true;
        for (int i = 0; i < e[u].size(); i++)
        {
            int v = e[u][i];
            if (!vis[v])
                dfs(v);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            e[u].push_back(v);
        }
        dfs(1); // 把所有 1 相连的点的 vis 标为真
        int ans = 1;
        for (int i = 2; i <= n; i++)
            if (vis[i])
                ans = i;
        cout << ans;
        return 0;
    }
    

    链式前向行做法

    在目前的比赛环境中已无太多优势,只有一个能快速找到反向边的优势,但也可以替代。

    因此,略。

    • 1

    信息

    ID
    1197
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    69
    已通过
    31
    上传者