提到图论中的搜索问题,首先想到的也就是DFS和BFS了,而提到这两种搜索,那么最典型的题目就是岛屿问题了,下面就练习几道相关的题目,为之后的更深奥的图论学习打下基础!

孤岛的总面积

题目链接:孤岛的总面积

这道题,顾名思义就是求孤岛的面积之和,所谓的孤岛就是地图中间的岛屿,也就是需要将地图边界上的岛屿不考虑,那怎么不考虑呢?很简单,我们只需要遍历地图的四个边界,然后遇到一个陆地就用DFS将与之相连的所有陆地变为海洋即可,然后遍历一遍地图,如果还有陆地的话那么他,就是孤岛了,因为要求总面积,所以遇到一个陆地就将面积++即可。

//https://kamacoder.com/problempage.php?pid=1173
//孤岛的总面积
#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int N = 55;
vector<vector<int>> mp(N,vector<int>(N));
int n,m,ans=0;
void pre_handle()
{}
int dis[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};void dfs(int x,int y)
{mp[x][y] = 0;for(int i=0;i<4;i++){int tx = x + dis[i][0];int ty = y + dis[i][1];if(tx < 1 || tx > n || ty < 1 || ty > m) continue;if(mp[tx][ty] == 1) dfs(tx,ty);}
}
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>mp[i][j];for(int i=1;i<=n;i++) if(mp[i][1] == 1) dfs(i,1);for(int i=1;i<=n;i++) if(mp[i][m] == 1) dfs(i,m);for(int i=1;i<=m;i++) if(mp[1][i] == 1) dfs(1,i);for(int i=1;i<=m;i++) if(mp[n][i] == 1) dfs(n,i);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(mp[i][j] == 1)ans++;cout<<ans<<endl;
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

沉没孤岛

题目链接:沉没孤岛

这道题和上一道题的思路是完全反过来即可,因为要让所有的孤岛沉没,所以就需要找出哪些是孤岛哪些不是孤岛,上一题中的代码已经将二者区分出来了,这道题我们只需要将标记为孤岛的陆地作为海洋输出即可,而非孤岛的陆地可以用其他的数字区分出来,如果用0的话就分不清是海洋还是陆地了,如果用1的话就分不清是否为孤岛了。

//https://kamacoder.com/problempage.php?pid=1174
//沉没孤岛
#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int N = 55;
vector<vector<int>> mp(N,vector<int>(N));
// vector<vector<bool>> v(N,vector<bool>(N));
int n,m,ans=0;
void pre_handle()
{}
int dis[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};void dfs(int x,int y)
{mp[x][y] = 2;for(int i=0;i<4;i++){int tx = x + dis[i][0];int ty = y + dis[i][1];if(tx < 1 || tx > n || ty < 1 || ty > m) continue;if(mp[tx][ty] == 1) dfs(tx,ty);}
}
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>mp[i][j];for(int i=1;i<=n;i++) if(mp[i][1] == 1) dfs(i,1);for(int i=1;i<=n;i++) if(mp[i][m] == 1) dfs(i,m);for(int i=1;i<=m;i++) if(mp[1][i] == 1) dfs(1,i);for(int i=1;i<=m;i++) if(mp[n][i] == 1) dfs(n,i);// for(int i=1;i<=n;i++)// for(int j=1;j<=m;j++)// if(mp[i][j] == 1) v[i][j] = 1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(mp[i][j] == 2) cout<<1<<' ';else cout<<0<<' ';}cout<<endl;}
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

水流问题

题目链接:水流问题

这道题正向思维是遍历每一个点然后去搜索他附近的比他低的点,但是这样时间复杂度是很高的,所以我们可以借助逆向思维,因为他要求必须既能流到第一边界又能流到第二边界,所以我们可以从两个边界开始搜索比他高的位置,然后将所有的相邻的比他高的位置都给标记出来,这个操作可以用两个bool类型的数组来完成,最后只需要遍历每个点,如果这个点被两个标记数组给标记可达了,那么这个点就是所求的点,直接输出即可,思路很简单,但是实现起来较有难度。

//https://kamacoder.com/problempage.php?pid=1175
//水流问题
#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int N = 105;
vector<vector<int>> mp(N,vector<int>(N));
vector<vector<bool>> v1(N,vector<bool>(N,0)),v2(N,vector<bool>(N,0));
int n,m,ans=0;
void pre_handle()
{}
int dis[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};void dfs1(int x,int y)
{if(v1[x][y]) return ;v1[x][y] = true;for(int i=0;i<4;i++){int tx = x + dis[i][0];int ty = y + dis[i][1];if(tx < 1 || ty < 1 || tx > n || ty > m) continue;if(v1[tx][ty] == false && mp[tx][ty] >= mp[x][y]) dfs1(tx,ty);}
}
void dfs2(int x,int y)
{if(v2[x][y]) return ;v2[x][y] = true;for(int i=0;i<4;i++){int tx = x + dis[i][0];int ty = y + dis[i][1];if(tx < 1 || ty < 1 || tx > n || ty > m) continue;if(v2[tx][ty] == false && mp[tx][ty] >= mp[x][y]) dfs2(tx,ty);}
}
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>mp[i][j];for(int i=1;i<=n;i++) dfs1(i,1);//"1"for(int i=1;i<=n;i++) dfs2(i,m);//"2"for(int i=1;i<=m;i++) dfs1(1,i);//"1"for(int i=1;i<=m;i++) dfs2(n,i);//"2"for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)if(v1[i][j] && v2[i][j])cout<<i-1<<' '<<j-1<<endl;}
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

建造最大岛屿

题目链接:建造最大岛屿

这道题是相对复杂的一道题了,想了很久的优化方法,后来看了题解,感觉又长脑子了,其实不需要对每一个点都去搜索,我们可以在一开始就先用普通的搜索方式将每一个岛屿都编号统一起来,编号要直接赋值地图上然后将对应的编号的岛屿的面积映射关系存起来,然后在遍历每一个为海洋的点的时候只需要看他的上下左右四个方向是否是岛屿然后将面积加起来即可,注意以下两个坑:

1.可能全部都是陆地,这时候就需要将存面积的数组中的值作为答案了

2.要注意海洋点的四个方向有可能存在相同编号的陆地,所以需要在对四个方向分析的时候用一个bool数组存起来作为访问标记,防止重复访问累加面积

代码实现起来极为恶心。 

//https://kamacoder.com/problempage.php?pid=1176
//建造最大岛屿
#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int N = 55;
int s=0;
vector<vector<int>> mp(N,vector<int>(N));
unordered_map<int,int> f;
int n,m,ans=0;
void pre_handle()
{}
int dis[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};void dfs(int x,int y,int mark)
{s++;mp[x][y] = mark;for(int i=0;i<4;i++){int tx = x + dis[i][0];int ty = y + dis[i][1];if(tx < 1 || tx > n || ty < 1 || ty > m) continue;if(mp[tx][ty] == 1) dfs(tx,ty,mark);}
}
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>mp[i][j];int index=2;//岛屿的编号、面积for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(mp[i][j] == 1){s=0;dfs(i,j,index);f[index++] = s;}}}int ans=0;for(auto i : f) ans = max(ans,i.se);//防止没有0的情况 !!!for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(mp[i][j] == 0){unordered_map<int,bool> v;int t=1;if(mp[i-1][j] && !v[mp[i-1][j]]){t+=f[mp[i-1][j]];v[mp[i-1][j]] = true;}if(mp[i+1][j] && !v[mp[i+1][j]]){t+=f[mp[i+1][j]];v[mp[i+1][j]] = true;}if(mp[i][j-1] && !v[mp[i][j-1]]){t+=f[mp[i][j-1]];v[mp[i][j-1]] = true;}if(mp[i][j+1] && !v[mp[i][j+1]]){t+=f[mp[i][j+1]];v[mp[i][j+1]] = true;}ans = max(ans,t);}}}cout<<ans<<endl;
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

岛屿的周长

这道题其实不是一道搜索题,直接遍历一遍将每个陆地点的上下左右四个方向的情况做一个判断即可,但是需要注意的是,周长需要++的情况就是1.该点作为陆地边界 2.该点作为地图边界,其实归根结底,都是遇到边界上的陆地就周长++,所以用1为初始的下标索引可以更简便的统计周长,因为不管是哪一种边界,都不会导致数组越界而且都是0。

//https://kamacoder.com/problempage.php?pid=1178
//岛屿的周长
#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int N = 55;
vector<vector<int>> mp(N,vector<int>(N));
int n,m,ans;
void pre_handle()
{}
int dis[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};void dfs(int x,int y)
{}
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>mp[i][j];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(mp[i][j] == 1){if(mp[i-1][j] == 0) ans++;if(mp[i+1][j] == 0) ans++;if(mp[i][j+1] == 0) ans++;if(mp[i][j-1] == 0) ans++;}}}cout<<ans<<endl;
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

字符串接龙 

题目链接:字符串接龙

这是一道结合了建图以及最短路的题,一般无权图求最短路直接用搜索即可,这道题用BFS即可

这道题有两个难点:怎么建图,怎么求最短路?

建图的还就需要对每个字符串进行枚举所有可能变成的字符串,如果在字典中出现了,就说明这两个字符串之间是可达的,可达的情况下就去判断是否已经搜索过这个点了(因为BFS要求一个点只能搜一遍),在没有搜索过的条件下再加入队列开始搜索。

整体思路如下:

用一个set来储存字典中的单词(因为元素是string类型,而相对map来说内存更小)是只读判断存在状态的最佳容器。

然后用一个map存放每个单词以及映射的路径长度(和普通的BFS一样 只不过普通的BFS在两个数组中存放了当前位置的路径长度以及访问状态,这是string类型,只能利用map的映射关系来实现既能对是否访问的判断又能储存路径长度)

最后就是枚举了,从BFS开始的队首元素开始不断的枚举所有的能变成的字典中的元素,第一次达到就直接入队进行搜索即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se secondvoid pre_handle()
{} void solve()
{int n;cin>>n;string s1,s2;cin>>s1>>s2;unordered_set<string> st;//字符串字典unordered_map<string,int> mp;//用于存放从起始字符串到当前的最短距离(通过BFS计算)//同时还可以记录该字符串是否被访问过了for(int i=1;i<=n;i++){string x;cin>>x;st.insert(x);}queue<string> q;q.push(s1);mp[s1] = 1;while(!q.empty())//BFS{string now = q.front();q.pop();int step = mp[now];for(int i=0;i<now.size();i++){string t = now;for(int j=0;j<26;j++)//遍历每一种情况 如果在字典中出现就说明可以连起来{t[i] = 'a' + j;if(t == s2){cout<<mp[now] + 1;return ;}//可以连起来的话就可以进行搜索了,但是BFS的前提是每个点只访问一次 所以当前字符串必须是首次出现if(st.find(t) != st.end() && mp.find(t) == mp.end()){q.push(t);mp[t] = step + 1;}}}}cout<<0<<endl;
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

有向图的完全联通 

点少边多:邻接矩阵

点多边少:邻接表

这道题是有向图的入门题目

首先需要将图建立起来,然后用dfs去遍历所有可达点即可,如果能遍历到所有点就是1否则就是-1

注意图的遍历的话需要有递归终止条件,每个点必须值访问异一次,防止死循环。

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int N = 1e2+10;
vector<int> e[N];
vector<bool> v(N,0);
void pre_handle()
{} 
void dfs(int x)
{if(v[x] == true) return ;//防止重复访问v[x] = true;//存的都是可达点 所以无需判断for(auto i : e[x]) dfs(i);    
}
void solve()
{int n,m;cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);}dfs(1);for(int i=1;i<=n;i++){if(v[i] == false){cout<<"-1"<<endl;return ;}}cout<<"1"<<endl;
}signed main()
{IOSint T=1;pre_handle();
//	cin>>T;while(T--) solve(); return 0;
} 

最后注意使用BFS(广度优先搜索的时候元素一旦入队就将其标记为已访问)

期待后续的并查集和迪杰斯特拉算法吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92885.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92885.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/92885.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI驱动攻防升级,API安全走到关键档口

在数字化转型与AI技术快速发展的双重驱动下&#xff0c;API已成为企业业务与外部世界连接的神经中枢。然而&#xff0c;随着API的深度应用&#xff0c;针对API的攻击规模与复杂性也在持续升级。 API为何频频成为黑客重点盯防的突破口&#xff1f;企业常见的API防护手段是否还能…

网络基础DAY18-动态路由协议基础

动态路由协议基础知识回顾&#xff1a;1.什么是路由&#xff1f; 答&#xff1a;是三层设备转发IP报文的路径信息。 2.路由有哪些来源&#xff1f; 答&#xff1a;1.直连路由2.静态路由3.动态路由 3.有直连路由的条件&#xff1f; 答&#xff1a;1.二层和三层物理接口状态为UP …

axios统一封装规范管理

新建/api/ 1.新建统一处理文件/api/axios.ts import axios from "axios"const http axios.create({baseURL: import.meta.env.VITE_API_BASE_URL, // 从环境变量读取timeout: 10000, });// 请求拦截器&#xff08;如添加 Token&#xff09; http.interceptors.reque…

Java学习第七十四部分——Elasticsearch(ES)

目录 一、前言提要 二、核心特性 三、应用场景 四、主要优势 五、集成方式 六、基础操作 七、高级特性 八、概念类比——与关系型数据库 九、简单示例——实现存储与搜索 十、生态集成——基于Spring Data Elasticsearch 十一、性能优化建议 十二、总结归纳概述 一…

TDengine 转化函数 TO_UNIXTIMESTAMP 用户手册

TDengine TO_UNIXTIMESTAMP 函数用户使用手册 函数概述 TO_UNIXTIMESTAMP 是 TDengine 中的标量函数&#xff0c;用于将符合 ISO8601/RFC3339 标准的日期时间字符串转换为 Unix 时间戳。与 TO_TIMESTAMP 不同&#xff0c;该函数专门处理标准格式的时间字符串&#xff0c;无需指…

Java 中的排序算法详解

目录 一、冒泡排序&#xff08;Bubble Sort&#xff09; 原理​ 二、选择排序&#xff08;Selection Sort&#xff09; 原理​ 三、插入排序&#xff08;Insertion Sort&#xff09; 原理​ 四、快速排序&#xff08;Quick Sort&#xff09; 原理​ 五、归并排序&…

Gitee如何成为国内企业DevOps转型的首选平台?

Gitee如何成为国内企业DevOps转型的首选平台&#xff1f; 在数字化转型浪潮中&#xff0c;DevOps已成为提升企业研发效能的关键引擎。作为国内领先的代码托管与协作平台&#xff0c;Gitee凭借本土化优势与全流程支持能力&#xff0c;正成为越来越多企业DevOps实践的核心载体。本…

​Excel——SUMPRODUCT 函数

SUMPRODUCT 是 Excel 中最强大的函数之一&#xff0c;可以用于 ​多条件求和、加权计算、数组运算​ 等复杂场景。下面通过 ​基础语法 实用案例​ 彻底讲透它的用法&#xff01;​一、基础语法​SUMPRODUCT(数组1, [数组2], [数组3], ...)​功能​&#xff1a;将多个数组的对…

告别虚函数性能焦虑:深入剖析C++多态的现代设计模式

🚀 引言:当多态遇上性能瓶颈 我经常被问到这样一个问题:“既然virtual函数这么方便,为什么在一些高性能场景下,大家却避之不及?” 答案很简单:性能。 在我参与的多个HPC项目和游戏引擎开发中,virtual函数调用往往成为性能分析工具中最显眼的那个红点。一个看似无害…

k8s-MongoDB 副本集部署

前提准备一套 k8s 集群worker 节点上的 /nfs/data 目录挂载到磁盘一、NFS 高可用方案&#xff08;NFSkeepalivedSersync&#xff09;本方案 NFS 的高可用方案&#xff0c;应用服务器为 Client &#xff0c;两台文件服务器分别 Master 和 Slave&#xff0c;使用 keepalived 生成…

BI 系统数据看板全解析:让数据可视化驱动业务决策

BI 系统数据看板全解析&#xff1a;让数据可视化驱动业务决策在 BI 系统中&#xff0c;数据看板是连接原始数据与业务洞察的 “桥梁”。它将零散的业务指标转化为直观的可视化图表&#xff0c;让产品经理、运营人员等角色能快速把握业务动态。一个设计精良的数据看板&#xff0…

图机器学习(14)——社交网络分析

图机器学习&#xff08;14&#xff09;——社交网络分析0. 前言1. 数据集分析1.1 数据集介绍1.2 使用 networkx 加载数据集2. 网络拓扑和社区检测2.1 网络拓扑2.2 社区检测0. 前言 社交网站的崛起是近年来数字媒体领域最活跃的发展趋势之一&#xff0c;数字社交互动已经融入人…

深入解析Hadoop MapReduce中Reduce阶段排序的必要性

MapReduce概述与Reduce阶段简介MapReduce作为Hadoop生态系统的核心计算框架&#xff0c;其设计思想源自Google论文&#xff0c;通过"分而治之"的理念实现海量数据的并行处理。该模型将计算过程抽象为两个关键阶段&#xff1a;Map阶段负责数据分解和初步处理&#xff…

7月23日华为机考真题第二题-200分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ bishipass.com 02. 图书馆资源分配系统 问题描述 A先生是一位图书馆管理员,负责管理图书采购和分配工作。图书馆收到了来自不同出版社的图书批次,同时有多位读者代表排队申请图书…

基于深度学习的图像分类:使用ResNet实现高效分类

最近研学过程中发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击链接跳转到网站人工智能及编程语言学习教程。读者们可以通过里面的文章详细了解一下人工智能及其编程等教程和学习方法。下面开始对正文内容的…

JVM:工具

JVMjpsjstatjmapjhatjstackjconsolejvisualvmjps jps&#xff08; Java Virtual Machine Process Status Tool &#xff09;&#xff0c;是 JDK 中的一个命令行工具&#xff0c;用于列出当前正在运行的 JVM 实例的信息。其对于监控和管理运行在多个 JVM 上的 Java 应用程序特别…

Elasticsearch Circuit Breaker 全面解析与最佳实践

一、Circuit Breaker 简介 Elasticsearch 是基于 JVM 的搜索引擎&#xff0c;其内存管理十分重要。为了避免单个操作或查询耗费过多内存导致节点不可用&#xff0c;Elasticsearch 引入了 Circuit Breaker&#xff08;熔断器&#xff09;机制。当内存使用达到熔断器预设阈值时&a…

ARM-定时器-定时器函数封装配置

以TIMER7为例&#xff0c;对定时器函数进行封装注意事项&#xff1a;GD32中TIMER7是高级定时器&#xff0c;相关详细请参考上一篇文章。main.c//main.c#include "gd32f4xx.h" #include "systick.h" #include <stdio.h> #include "main.h" …

【日志】unity俄罗斯方块——边界限制检测

Bug修复记录 项目场景 尝试使用Unity独自制作俄罗斯方块&#xff08;也许很没有必要&#xff0c;网上随便一搜就有教程&#xff09; 问题描述 俄罗斯方块的边缘检测出错了&#xff0c;对方块进行旋转后&#xff0c;无法到达最左侧或者最下侧的位置&#xff0c;以及其他问题。演…

C++ string:准 STL Container

历史STL 最初是一套独立的泛型库&#xff08;Alexander Stepanov 等人贡献&#xff09;&#xff0c;后来被吸纳进 C 标准库&#xff1b;std::basic_string 则是早期 C 标准&#xff08;Cfront / ARM 时代&#xff09;就存在的“字符串类”&#xff0c;并非 STL 原生物。std::st…