当前位置:首页 > 技术 > 正文内容

图论:寻找所有可能路径的算法

访客 技术 2026年8月12日 1
  1. 所有可能的路径

思路一:深度优先搜索(DFS)

void searchPaths(vector<vector<int>> &graph, int currentNode, int targetNode): 使用深度优先搜索(DFS)方法,用于探索从节点currentNode到节点targetNode的所有路径。 逻辑:

  • 如果当前节点currentNode是目标节点targetNode,将当前路径path添加到allPaths中。
  • 遍历graph[currentNode]中的每个相邻节点nextNode
  • 将节点nextNode添加到当前路径path
  • 递归调用searchPaths以继续探索从nextNode开始的路径。
  • 回溯:从path中移除节点nextNode,以探索其他可能的路径。

vector<vector<int>> findAllPaths(vector<vector<int>>& graph): 这是解决问题的主方法,返回从起点到终点的所有路径。 逻辑: 将起点0添加到当前路径path。 调用searchPaths方法,从起点0开始探索到终点n的路径。 返回存储了所有路径的allPaths

代码一:

class Solution {
public:
    vector<vector<int>> allPaths;
    vector<int> path;

    void searchPaths(vector<vector<int>> &graph, int currentNode, int targetNode) {
        if (currentNode == targetNode) {
            allPaths.push_back(path);
            return;
        }
        for (auto &nextNode : graph[currentNode]) {
            path.push_back(nextNode);
            searchPaths(graph, nextNode, targetNode);
            path.pop_back();
        }
    }

    vector<vector<int>> findAllPaths(vector<vector<int>>& graph) {
        path.push_back(0);
        searchPaths(graph, 0, graph.size() - 1);
        return allPaths;
    }
};

思路二:广度优先搜索(BFS)

  1. 初始化:
  • 创建一个队列 queue 来存储路径。
  • 将初始路径 {0}(只包含起点)放入队列。
  1. 目标节点:
  • 设定目标节点为 target = graph.size() - 1,即图的最后一个节点。
  1. BFS循环:
  • 当队列不为空时,执行以下步骤:
  • 从队列中取出一个路径 currentPath
  • 获取路径的最后一个节点 lastNode
  • 如果 lastNode 是目标节点,将当前路径加入结果 allPaths
  • 否则,遍历 lastNode 的所有相邻节点 nextNode
  • 创建一个新路径 newPath,将 nextNode 添加到 currentPath
  • newPath 放入队列。
  1. 返回结果:
  • 当队列为空时,所有路径都已找到,返回结果 allPaths

代码二:

class Solution {
public:
    vector<vector<int>> findAllPaths(vector<vector<int>>& graph) {
        vector<vector<int>> allPaths;
        queue<vector<int>> queue;
        queue.push({0});
        int target = graph.size() - 1;
        while (!queue.empty()) {
            vector<int> currentPath = queue.front();
            queue.pop();
            int lastNode = currentPath.back();
            if (lastNode == target) allPaths.push_back(currentPath);
            else {
                for (auto &nextNode : graph[lastNode]) {
                    vector<int> newPath = currentPath;
                    newPath.push_back(nextNode);
                    queue.push(newPath);
                }
            }
        }
        return allPaths;
    }
};

ACM模式

邻接矩阵代码:

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

vector<vector<int>> results; // 收集符合条件的路径
vector<int> path; // 从起点到终点的路径

void searchPaths(const vector<vector<int>>& graph, int currentNode, int targetNode) {
    if (currentNode == targetNode) { // 找到符合条件的一条路径
        results.push_back(path);
        return;
    }
    for (int i = 1; i <= targetNode; i++) { // 遍历节点currentNode链接的所有节点
        if (graph[currentNode][i] == 1) { // 找到 currentNode链接的节点
            path.push_back(i); // 遍历到的节点加入到路径中来
            searchPaths(graph, i, targetNode); // 进入下一层递归
            path.pop_back(); // 回溯,撤销本节点
        }
    }
}

int main() {
    int n, m, s, t;
    cin >> n >> m;

    // 节点编号从1到n,所以申请 n+1 这么大的数组
    vector<vector<int>> graph(n + 1, vector<int>(n + 1, 0));

    while (m--) {
        cin >> s >> t;
        // 使用邻接矩阵 表示无线图,1 表示 s 与 t 是相连的
        graph[s][t] = 1;
    }

    path.push_back(1); // 无论什么路径已经是从起点出发
    searchPaths(graph, 1, n); // 开始遍历

    // 输出结果
    if (results.size() == 0) cout << -1 << endl;
    for (const vector<int> &pa : results) {
        for (int i = 0; i < pa.size() - 1; i++) {
            cout << pa[i] << " ";
        }
        cout << pa[pa.size() - 1] << endl;
    }
}

邻接表代码:

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

vector<vector<int>> results; // 收集符合条件的路径
vector<int> path; // 从起点到终点的路径

void searchPaths(const vector<list<int>>& graph, int currentNode, int targetNode) {
    if (currentNode == targetNode) { // 找到符合条件的一条路径
        results.push_back(path);
        return;
    }
    for (int i : graph[currentNode]) { // 找到 currentNode指向的节点
        path.push_back(i); // 遍历到的节点加入到路径中来
        searchPaths(graph, i, targetNode); // 进入下一层递归
        path.pop_back(); // 回溯,撤销本节点
    }
}

int main() {
    int n, m, s, t;
    cin >> n >> m;

    // 节点编号从1到n,所以申请 n+1 这么大的数组
    vector<list<int>> graph(n + 1); // 邻接表
    while (m--) {
        cin >> s >> t;
        // 使用邻接表 ,表示 s -> t 是相连的
        graph[s].push_back(t);
    }

    path.push_back(1); // 无论什么路径已经是从起点出发
    searchPaths(graph, 1, n); // 开始遍历

    // 输出结果
    if (results.size() == 0) cout << -1 << endl;
    for (const vector<int> &pa : results) {
        for (int i = 0; i < pa.size() - 1; i++) {
            cout << pa[i] << " ";
        }
        cout << pa[pa.size() - 1] << endl;
    }
}
标签: 图论DFS

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。