【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;
}

二、写在后面

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

相关推荐
菜鸟破茧计划3 分钟前
滑动窗口:穿越数据的时光机
java·数据结构·算法
_Itachi__1 小时前
LeetCode 热题 100 101. 对称二叉树
算法·leetcode·职场和发展
少了一只鹅1 小时前
深入理解指针(5)
java·c语言·数据结构·算法
朱剑君2 小时前
第三天——贪心算法——区间问题
算法·贪心算法
阳洞洞2 小时前
leetcode 15. 三数之和
leetcode·双指针
Mi Manchi263 小时前
力扣热题100之合并两个有序链表
算法·leetcode·链表
阿沁QWQ3 小时前
C语言中的文本读写和二进制读写接口
开发语言·c++·算法
仙人掌_lz3 小时前
深入理解深度Q网络DQN:基于python从零实现
python·算法·强化学习·dqn·rl
小雅痞3 小时前
[Java][Leetcode middle] 80. 删除有序数组中的重复项 II
java·python·leetcode
TsingtaoAI4 小时前
企业内训|智能调控系统算法与优化——某汽车厂商
算法·汽车·ai企业内训·自动驾驶企业内训·智驾企业培训