【Day45 LeetCode】图论问题 Ⅲ

news/2025/2/25 17:45:29

一、图论问题 Ⅲ

1、沉没孤岛

这题只能从边界开始扩散,将靠近边界的陆地标记,表示不是孤岛,最后将孤岛沉没,将不是孤岛标记回陆地。

# 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];
    
    // 步骤一:
    // 从左侧边,和右侧边 向中间遍历
    for (int i = 0; i < n; i++) {
        if (graph[i][0] == 1) dfs(graph, i, 0);
        if (graph[i][m - 1] == 1) dfs(graph, i, m - 1);
    }

    // 从上边和下边 向中间遍历
    for (int j = 0; j < m; j++) {
        if (graph[0][j] == 1) dfs(graph, 0, j);
        if (graph[n - 1][j] == 1) dfs(graph, n - 1, j);
    }


    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (graph[i][j] == 1) graph[i][j] = 0;
            if (graph[i][j] == 2) graph[i][j] = 1;
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << graph[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

2、水流问题

如果想着从当前点向两个边界移动的话,时间复杂度过高,因为需要遍历每个点,每个点又需要扩散到两个边界。如果我们逆向思维,想着从边界出发去找可达的点,这一下就豁然开朗了。

# include<iostream>
# include<vector>

using namespace std;

vector<vector<int>> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
void dfs(vector<vector<int>> &graph, vector<vector<bool>> &vis,int ii, int jj){
    if(vis[ii][jj])
        return;
    vis[ii][jj] = true;
    for(auto xy : dirs){
        int i = ii + xy[0], j = jj + xy[1];
        if(i<0 || i>=graph.size() || j<0 || j>=graph[0].size() || graph[ii][jj] > graph[i][j] || vis[i][j])
            continue;
        dfs(graph, vis, i, j);
    }
}


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];
    
    vector<vector<bool>> vis1(n, vector<bool>(m, false));
    vector<vector<bool>> vis2(n, vector<bool>(m, false)); 
    
    for(int i=0; i<n; ++i){
        dfs(graph, vis1, i, 0);
        dfs(graph, vis2, i, m-1);
    }
    for(int i=0; i<m; ++i){
        dfs(graph, vis1, 0, i);
        dfs(graph, vis2, n-1, i);
    }
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(vis1[i][j] && vis2[i][j])
                cout << i << " " << j << endl;
        }
    }
    return 0;
}

3、建造最大岛屿

写了个很不优雅的代码,思路是 DFS遍历陆地,给每个岛屿一一对应的编号,并用哈希表记录编号与岛屿面积的对应关系。然后,第二次遍历图,遇到水域,遍历水域的四个方向上的编号,进行面积累加,一个细节是需要用set进行去重,可能四个反向上存在编号相同的区域。

# include<iostream>
# include<vector>
# include<unordered_map>
# include<unordered_set>
using namespace std;

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

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];
    unordered_map<int, int> mp; // 映射几号陆地 与 其面积关系
    mp[0] = 0;
    int idx = 2; // 几号陆地 
    int ans = 0;
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(graph[i][j]==1){
                mp[idx] = dfs(graph, i, j, idx);
                ans = max(ans, mp[idx]);
                ++idx;
            }
        }
    }
    vector<vector<int>> dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(graph[i][j]==0){
                int tmp = 1;
                unordered_set<int> set;
                for(auto xy : dirs){
                    int x = i + xy[0], y = j + xy[1];
                    if(x>=0 && x<n && y>=0 && y<m && set.find(graph[x][y])==set.end()){
                        set.insert(graph[x][y]);
                        tmp += mp[graph[x][y]];
                    }
                }
                ans = max(ans, tmp);
            }
        }
    }
    cout << ans << endl;
    
    return 0;
}

http://www.niftyadmin.cn/n/5865782.html

相关文章

ViT 模型介绍(三)——简单实战项目

用 ViT 做一个简单的图像分类任务 在 CIFAR-10 数据集上进行图像分类。通过 Hugging Face 的 transformers 库&#xff0c;加载一个预训练的 ViT 模型&#xff0c;并使用 PyTorch 进行微调。通过训练模型&#xff0c;评估测试集上的准确性&#xff0c;并可视化部分预测结果 可…

跨境宠物摄像头是一种专为宠物主人设计的智能设备

跨境宠物摄像头是一种专为宠物主人设计的智能设备&#xff0c;它结合了摄像头技术和互联网通信功能&#xff0c;使宠物主人能够远程监控和互动家中的宠物。以下是对跨境宠物摄像头的详细介绍&#xff1a; 一、主要特点 1. 远程监控&#xff1a;宠物主人可以通过手机等移动设备…

Three.js 快速入门教程【八】常见材质类型

系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六】相机控件 Or…

流媒体网络协议全解析:从实时传输到自适应流,如何选择最优方案?

一、历史发展与协议提出者 流媒体协议的发展与互联网技术迭代紧密相关,主要分为三个阶段: 早期专有协议(1990s-2000s) RTSP/RTP 提出者:RealNetworks(RTSP初始推动者),后由IETF标准化(RFC 2326)。背景:1996年推出,用于视频监控和点播系统,基于UDP传输媒体流,支持…

详解golang的Gengine规则引擎

一:简介 Gengine是一款基于golang和AST(抽象语法树)开发的规则引擎, Gengine支持的语法是一种自定义的DSL, Gengine通过内置的解释器对规则文件进行解析,构建规则模型,进行相应的规则计算和数据处理。Gengine于2020年7月由哔哩哔哩(bilibili.com)授权开源。Gengine现已应用…

前端学习—HTML

前端学习 html概括 HTML结构标签定义网页内容 CSS样式配置&#xff0c;规定网页布局 JavaScript编程网页行为 HTML超文本标记语言&#xff0c;是一套标记标签&#xff0c;描述网页的 XHTML是以XML格式编写的HTML HTML文档也叫web页面&#xff0c;由互相嵌套的HTML元素构…

机试题——新能源汽车充电桩建设策略

题目描述 随着新能源汽车的蓬勃发展&#xff0c;新能源汽车充电桩的覆盖密度越来越重要。某汽车公司建设充电桩的思路如下&#xff1a; 一条高速沿线&#xff0c;每个区域建设一个充电站&#xff0c;充电站内有多个充电桩&#xff0c;充电站之间保持合理的距离。每个充电站可…

C#开发——ConcurrentDictionary集合

ConcurrentDictionary<TKey, TValue> 是 C# 中一个专为多线程场景设计的线程安全字典集合&#xff0c;位于 System.Collections.Concurrent 命名空间中。它允许多个线程同时对字典进行读写操作&#xff0c;而无需额外的同步措施。 一、集合特征 此集合有如下特征…