图论
题目
110. 字符串接龙
给出开始与结束的字符串,给出字符串 list,返回从字符串开始到结束过程中最短的路径
难点在于:求起点与终点的最短路径,通过广度优先搜索实现
对原始的字符串逐个位进行替换,匹配是否出现在 list 中,出现了就记录到 map 中,直到找到字符
在无权图中,用广搜求最短路最为合适,广搜只要搜到了终点,那么一定是最短的路径。因为广搜就是以起点中心向四周扩散的搜索。
本题如果用深搜,会比较麻烦,要在到达终点的不同路径中选则一条最短路。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <queue>
using namespace std;
int main() {
// 数据处理
int n;
string beginStr, endStr, str;
unordered_set<string> strSet;
cin >> n;
cin >> beginStr >> endStr;
for (int i = 0; i < n; ++i) {
cin >> str;
strSet.insert(str);
}
// 记录访问情况
unordered_map<string, int> vis;
queue<string> que;
que.push(beginStr);
vis.insert(make_pair(beginStr, 1));
// 广度优先搜索遍历
while (!que.empty()) {
string word = que.front();
que.pop();
// 记录路径长度
int path = vis[word];
for (int i = 0; i < word.size(); ++i) {
string newWord = word;
for (int j = 0; j < 26; ++j) {
newWord[i] = j + 'a';
// 经过变换到达了目标字符
if (newWord == endStr) {
cout << path + 1 << endl;
return 0;
}
// 记录字符变化过程
if (strSet.find(newWord) != strSet.end() && vis.find(newWord) == vis.end()) {
vis.insert({newWord, path+1});
que.push(newWord);
}
}
}
}
// 找不到变换路径
cout << 0 << endl;
}
105. 有向图的完全联通
有向图的连通性判断,判断 1 是否可以到达所有节点
思路就是构造有向图,然后遍历图标记节点为 vis 为 true,最后遍历节节点,全为 true 则说明可访问
#include <iostream>
#include <vector>
#include <queue>
#include <list>
using namespace std;
void dfs(vector<list<int>>& graph, vector<bool>& vis, int idx) {
if (vis[idx]) return;
vis[idx] = true;
for (int key : graph[idx]) {
dfs(graph, vis, key);
}
}
// 需要预先处理vis[1] = ture
void dfs2(vector<list<int>>& graph, vector<bool>& vis, int idx) {
for (int key : graph[idx]) {
if (!vis[idx]) {
vis[idx] = true;
dfs(graph, vis, key);
}
}
}
void bfs(vector<list<int>>& graph, vector<bool>& vis) {
queue<int> que;
que.push(1);
vis[1] = true;
while (!que.empty()) {
list<int> lists = graph[que.front()];
que.pop();
for (int key: lists) {
if (!vis[key]) {
vis[key] = true;
que.push(key);
}
}
}
}
int main() {
// 构造图结构
int n, k;
cin >> n >> k;
// 使用邻接表构造
vector<list<int>> graph(n+1);
vector<bool> vis(n+1, false);
for (int i = 0; i < k; ++i) {
int s, t;
cin >> s >> t;
graph[s].push_back(t);
}
// 遍历图并检查是否完全访问
bfs(graph, vis);
// dfs(graph, vis, 1);
for (int i = 1; i < n; ++i) {
if (!vis[i]) {
cout << -1 <<endl;
return 0;
}
}
cout << 1 << endl;
return 0;
}
106. 岛屿的周长
岛屿周长不需要 DFS or BFS 只需要判断当前岛的四周如果是海洋或者是边界 +1 即可
有些岛屿题没那么难
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 输入处理
int n,m;
cin >> n >> m;
vector<vector<int>> grid(n, vector<int>(m, 0));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> grid[i][j];
}
}
// 遍历计算周长
int res = 0;
int dir[4][2] = {0,-1,-1,0,0,1,1,0};
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
// 找到陆地
if (grid[i][j] == 1) {
for (int k = 0; k < 4; ++k) {
int nextX = i + dir[k][0];
int nextY = j + dir[k][1];
if (nextX < 0 || nextX >= n || nextY < 0 || nextY >= m || grid[nextX][nextY] == 0) res++;
}
}
}
}
cout << res << endl;
return 0;
}