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

二、写在后面

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

相关推荐
Code_Solitude1 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司1 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
文丑颜不良啊2 小时前
LeetCode2821~2840题目解析
java·leetcode
YLCHUP4 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
思麟呀4 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落5 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
Pniubi6 小时前
力扣24. 两两交换链表中的节点(递归)
算法·leetcode·链表
꧁细听勿语情꧂7 小时前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法
文丑颜不良啊7 小时前
LeetCode2741~2760题目解析
java·leetcode
俊俊几年的7 小时前
动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100
linux·c++·算法·leetcode·嵌入式·动态规划·c