【Day 43 LeetCode】图论问题 Ⅰ

一、图论问题 Ⅰ

关于图论有关的基本概念可以先看这篇文章

图论相关问题需要掌握最基础也是最关键的就是 图的遍历方法。有深度优先遍历和广度优先遍历两种方式。

深度优先搜索代码实现就是采用递归,递归就涉及到三要素:参数、终止条件、循环搜索。

广度优先搜索代码实现就是采用迭代,适合求解两个节点的最短路径问题。

1、所有可达路径

采用邻接表来记录图,采用深度优先遍历寻找可达路径。这可以当作是深度优先搜索的模板。

CPP 复制代码
# include<iostream>
# include<vector>
# include<list>

using namespace std;

vector<vector<int>> result;
vector<int> path;

void dfs(vector<list<int>> &graph, int node, const int des){
    if(node==des){
        result.push_back(path);
        return;
    }
    for(int x : graph[node]){
        path.push_back(x);
        dfs(graph, x, des);
        path.pop_back();
    }
}

int main(){
    int m ,n, s, t; // n个节点 m条边
    cin >> n >> m;
    vector<list<int>> graph(n+1);
    for(int i=0; i<m; ++i){
        cin >> s >> t;
        graph[s].push_back(t);
    }
    path.push_back(1);
    dfs(graph, 1, n);
    // 输出结果
    if(result.size()==0)
        cout << -1 << endl;
    for(auto x : result){
        for(int i=0; i<x.size()-1; ++i)
            cout << x[i] << " ";
        cout << x.back() << endl;
    }
    return 0;
}

采用邻接矩阵记录图的代码:

CPP 复制代码
# include<iostream>
# include<vector>

using namespace std;

vector<vector<int>> result;
vector<int> path;

void dfs(vector<vector<int>> &graph, int node, const int des){
    if(node==des){
        result.push_back(path);
        return;
    }
    for(int i=1; i<=des; ++i){
        if(graph[node][i]==1){
            path.push_back(i);
            dfs(graph, i, des);
            path.pop_back();
        }
    }
}

int main(){
    int m ,n, s, t; // n个节点 m条边
    cin >> n >> m;
    vector<vector<int>> graph(n+1, vector<int>(n+1));
    for(int i=0; i<m; ++i){
        cin >> s >> t;
        graph[s][t] = 1;
    }
    path.push_back(1);
    dfs(graph, 1, n);
    // 输出结果
    if(result.size()==0)
        cout << -1 << endl;
    for(auto x : result){
        for(int i=0; i<x.size()-1; ++i)
            cout << x[i] << " ";
        cout << x.back() << endl;
    }
    return 0;
}

2、岛屿数量

找到陆地,然后以此陆地为起点,开始搜索,将其相连的陆地标记一下,表示组成岛屿。

下面是采用深度优先遍历的代码:

CPP 复制代码
# include<iostream>
# include<vector>

using namespace std;

void dfs(vector<vector<int>> &graph, int i, int j){
    if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[i][j]!=1)
        return;
    graph[i][j] = 2; // 标记
    dfs(graph, i+1, j);
    dfs(graph, i-1, j);
    dfs(graph, i, j+1);
    dfs(graph, i, j-1);
}

int main(){
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    for(int i=0; i<n; ++i)
        for(int j=0; j<m; ++j)
            cin >> graph[i][j];
    int ans = 0;
    // 开始查找岛屿
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(graph[i][j]==1){
                ++ans; // 找到岛屿
                // 将与该岛屿相关的陆地标记
                dfs(graph, i, j);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

广度优先遍历(迭代)的代码如下:

CPP 复制代码
# include<iostream>
# include<vector>
# include<queue>
using namespace std;

vector<vector<int>> dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
void bfs(vector<vector<int>> &graph, int i, int j){
    queue<pair<int, int>> q;
    graph[i][j] = 2;
    q.push({i, j});
    while(!q.empty()){
        auto cur = q.front(); q.pop();
        for(auto xy : dirs){
            int x = cur.first + xy[0];
            int y = cur.second + xy[1];
            if(x<0 || x>=graph.size() || y<0 || y>=graph[0].size() || graph[x][y]!=1)
                continue;
            graph[x][y] = 2;
            q.push({x, y});
        }
    }
}

int main(){
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    for(int i=0; i<n; ++i)
        for(int j=0; j<m; ++j)
            cin >> graph[i][j];
    int ans = 0;
    // 开始查找岛屿
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(graph[i][j]==1){
                ++ans; // 找到岛屿
                // 将与该岛屿相关的陆地标记
                bfs(graph, i, j);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

二、写在后面

图的遍历非常重要,是解决与图相关问题的基石,需要很熟练。

相关推荐
木子.李3472 分钟前
排序算法总结(C++)
c++·算法·排序算法
闪电麦坤951 小时前
数据结构:递归的种类(Types of Recursion)
数据结构·算法
Gyoku Mint2 小时前
机器学习×第二卷:概念下篇——她不再只是模仿,而是开始决定怎么靠近你
人工智能·python·算法·机器学习·pandas·ai编程·matplotlib
纪元A梦2 小时前
分布式拜占庭容错算法——PBFT算法深度解析
java·分布式·算法
px不是xp2 小时前
山东大学算法设计与分析复习笔记
笔记·算法·贪心算法·动态规划·图搜索算法
枫景Maple3 小时前
LeetCode 2297. 跳跃游戏 VIII(中等)
算法·leetcode
鑫鑫向栄3 小时前
[蓝桥杯]修改数组
数据结构·c++·算法·蓝桥杯·动态规划
鑫鑫向栄3 小时前
[蓝桥杯]带分数
数据结构·c++·算法·职场和发展·蓝桥杯
小wanga4 小时前
【递归、搜索与回溯】专题三 穷举vs暴搜vs回溯vs剪枝
c++·算法·机器学习·剪枝