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

二、写在后面

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

相关推荐
core51216 分钟前
PageRank 算法:互联网的“人气投票”
算法·pagerank
小白菜又菜19 分钟前
Leetcode 1523. Count Odd Numbers in an Interval Range
算法·leetcode
你们补药再卷啦1 小时前
人工智能算法概览
人工智能·算法
cnxy1881 小时前
围棋对弈Python程序开发完整指南:步骤3 - 气(Liberties)的计算算法设计
python·算法·深度优先
AndrewHZ1 小时前
【图像处理基石】什么是光栅化?
图像处理·人工智能·算法·计算机视觉·3d·图形渲染·光栅化
小白菜又菜1 小时前
Leetcode 944. Delete Columns to Make Sorted
算法·leetcode
我找到地球的支点啦2 小时前
Matlab系列(006) 一利用matlab保存txt文件和读取txt文件
开发语言·算法·matlab
Dev7z2 小时前
基于Matlab实现GRACE卫星重力数据的全球水储量变化估算与分析
人工智能·算法·matlab
爱喝热水的呀哈喽2 小时前
11题目汇总
算法
三斗米3 小时前
Transformer入门:一文读懂《Attention Is All You Need》
算法·架构