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

二、写在后面

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

相关推荐
老鼠只爱大米4 分钟前
LeetCode经典算法面试题 #78:子集(回溯法、迭代法、动态规划等多种实现方案详细解析)
算法·leetcode·动态规划·回溯·位运算·子集
执着2598 分钟前
力扣hot100 - 199、二叉树的右视图
数据结构·算法·leetcode
I_LPL11 分钟前
day21 代码随想录算法训练营 二叉树专题8
算法·二叉树·递归
可编程芯片开发18 分钟前
基于PSO粒子群优化PI控制器的无刷直流电机最优控制系统simulink建模与仿真
人工智能·算法·simulink·pso·pi控制器·pso-pi
cpp_250119 分钟前
P8448 [LSOT-1] 暴龙的土豆
数据结构·c++·算法·题解·洛谷
YGGP19 分钟前
【Golang】LeetCode 49. 字母异位词分组
leetcode
lcj251119 分钟前
深入理解指针(4):qsort 函数 & 通过冒泡排序实现
c语言·数据结构·算法
fie888921 分钟前
基于MATLAB的转子动力学建模与仿真实现(含碰摩、不平衡激励)
开发语言·算法·matlab
唐梓航-求职中28 分钟前
编程大师-技术-算法-leetcode-1472. 设计浏览器历史记录
算法·leetcode
_OP_CHEN31 分钟前
【算法基础篇】(五十八)线性代数之高斯消元法从原理到实战:手撕模板 + 洛谷真题全解
线性代数·算法·蓝桥杯·c/c++·线性方程组·acm/icpc·高斯消元法