当前位置:首页 > C++目录 > 正文内容

图的遍历

亿万年的星光2个月前 (11-30)C++目录177


【题目描述】

给出  个点, 条边的有向图,对于每个点 ,求  表示从点  出发,能到达的编号最大的点。

【输入】

第  行  个整数 ,表示点数和边数。

接下来  行,每行  个整数 ,表示边 。点用  编号。

【输出】

一行  个整数 

【输入样例】

4 3
1 2
2 4
4 3

【输出样例】

4 4 3 4

【提示】

对于  的数据,

对于  的数据,



【题目分析】

题目要求对于每个点
v,找出从它出发能到达的编号最大的点。

也就是说,如果从v出发,出发可以到达点x1,x2,x3....  那么

R(v)=max(x1,x2,x3.....)

其中也包括
v 本身(因为从vv 出发至少能到达自己)。


一个常见的思路是

反向图 + 按编号从大到小 BFS


一个常见的技巧是:


  • 建反向图(即原图中的边 
    u→v 变成 
    v→u)。

  • 从编号最大的点 N 开始 BFS,在反向图中能到达的点 x,意味着在原图中 x能到达 N

  • 那么这些点的答案至少是 N

  • 然后从 N1开始,如果它还没被访问过,就 BFS,能到达的点答案至少是 N1,但注意如果之前已经赋过更大的值,就不用更新。

  • 这样按编号从大到小做 BFS,每个点只会被访问一次,因为一旦被访问,它的答案就已经确定(是当前起点的编号,并且这个编号是递减考虑的,所以第一次访问时就是最大可能值)。



算法步骤:

  1. 构建反向图 rG

  2. 初始化答案数组 ans[i] = 0

  3. 从 i = N 到 1

    • 如果 i 还没有被访问过,从 i 开始在反向图上 BFS/DFS。

    • 在 BFS 过程中,对于每个到达的点 u,如果它还没被访问过,就设置 ans[u] = i,并标记访问,加入队列。

  4. 输出 ans[1..N]


【参考答案】

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int main() {
    int N, M;
    cin >> N >> M;

    vector<vector<int>> rG(N + 1);

    for (int i = 0; i < M; i++) {
        int u, v;
        cin >> u >> v;
        rG[v].push_back(u);
    }

    vector<int> ans(N + 1, 0);
    vector<bool> visited(N + 1, false);

    for (int i = N; i >= 1; i--) {
        if (visited[i]) continue;

        queue<int> q;
        q.push(i);
        visited[i] = true;
        ans[i] = i;

        while (!q.empty()) {
            int cur = q.front();
            q.pop();
            for (int j = 0; j < rG[cur].size(); j++) {
                int nxt = rG[cur][j];
                if (!visited[nxt]) {
                    visited[nxt] = true;
                    ans[nxt] = i;
                    q.push(nxt);
                }
            }
        }
    }

    for (int i = 1; i <= N; i++) {
        cout << ans[i];
        if (i < N) {
            cout << " ";
        }
    }
    cout << endl;

    return 0;
}


扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

分享给朋友:

相关文章

unsigned

在一些代码中,经常能看到unsigned这种数据类型,比如下面这样的。#include<iostream> using namespace std; int&nbs...

CSP-J2021年普及组复赛T4——小熊的果篮

【题目描述】    小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依 次用正整数 1、2、3、……、n 编号。连续排在一起的同一种...

最小生成树—基本概念

一、最小生成树核心概念1. 基本定义一个带权无向连通图的最小生成树,是指从该图中选择若干条边,构成一个包含图中所有顶点的树结构(无环、连通),且所有选中边的权值之和最小。2. 关键性质生成树的本质:包...

【题解】最短路径问题

【题目描述】平面上有n个点(n≤100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现...

CSP复赛必备,时间与空间估算

CSP复赛必备,时间与空间估算

一、时间估算       在竞赛环境中,一般运行程序的时间是1s。这要求我们尽量不要循环太多次数,一般情况下,建议将时间复杂度控制在10^8以内。 ...

STL入门——容器3:map

一、定义    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据&nb...