图论day58|110.字符串接龙(卡码网)【难度等同于104】、105.有向图的完全可达性(卡码网)【深搜的终止条件要注意!】、106.岛屿的周长(卡码网)【打破惯性思维】
110.字符串接龙(卡码网)【难度等同于104】
题目描述
字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列:
- 序列中第一个字符串是 beginStr。
- 序列中最后一个字符串是 endStr。
- 每次转换只能改变一个字符。
- 转换过程中的中间字符串必须是字典 strList 中的字符串,且strList里的每个字符串只用使用一次。
给你两个字符串 beginStr 和 endStr 和一个字典 strList,找到从 beginStr 到 endStr 的最短转换序列中的字符串数目。如果不存在这样的转换序列,返回 0。
输入描述
第一行包含一个整数 N,表示字典 strList 中的字符串数量。 第二行包含两个字符串,用空格隔开,分别代表 beginStr 和 endStr。 后续 N 行,每行一个字符串,代表 strList 中的字符串。
输出描述
输出一个整数,代表从 beginStr 转换到 endStr 需要的最短转换序列中的字符串数量。如果不存在这样的转换序列,则输出 0。
输入示例
6
abc def
efc
dbc
ebc
dec
dfc
yhn
输出示例
4
提示信息
从 startStr 到 endStr,在 strList 中最短的路径为 abc -> dbc -> dec -> def,所以输出结果为 4,如图:
数据范围:
2 <= N <= 500
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <string>
using namespace std;
int main()
{
int n;
cin>>n;
string beginStr,endStr,str;
unordered_set<string> strList;
cin>>beginStr>>endStr;
for(int i=0;i<n;i++)
{
cin>>str;
strList.insert(str);
}
unordered_map<string,int> strMap;
queue<string> que;
que.push(beginStr);
strMap[beginStr]=1;
while(!que.empty())
{
string word=que.front();
que.pop();
int path=strMap[word];
for(int i=0;i<word.size();i++)
{
string newWord=word;
for(int j=0;j<26;j++)
{
newWord[i]='a'+j;
if(newWord==endStr)
{
cout<<path+1<<endl;
return 0;
}
if(strList.find(newWord)!=strList.end()&&
strMap.find(newWord)==strMap.end())
{
que.push(newWord);
strMap[newWord]=path+1;
}
}
}
}
cout<<0<<endl;
}
105.有向图的完全可达性(卡码网)【深搜的终止条件要注意!】
题目描述
给定一个有向图,包含 N 个节点,节点编号分别为 1,2,…,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。
输入描述
第一行包含两个正整数,表示节点数量 N 和边的数量 K。 后续 K 行,每行两个正整数 s 和 t,表示从 s 节点有一条边单向连接到 t 节点。
输出描述
如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。
输入示例
4 4
1 2
2 1
1 3
2 4
输出示例
1
提示信息
从 1 号节点可以到达任意节点,输出 1。
数据范围:
1 <= N <= 100;
1 <= K <= 2000。
#include <iostream>
#include <vector>
using namespace std;
int n,k;
void dfs(const vector<vector<int>>graph,vector<bool>& visited,int key)
{
if(visited[key]==true)
return;
visited[key]=true;
for(int i=1;i<=n;i++)
if(graph[key][i]==1)
dfs(graph,visited,i);
}
int main()
{
int s,t;
cin>>n>>k;
vector<vector<int>> graph(n+1,vector<int>(n+1,0));
for(int i=0;i<k;i++)
{
cin>>s>>t;
graph[s][t]=1;
}
vector<bool> visited(n+1,false);
dfs(graph,visited,1);
for(int i=1;i<=n;i++)
{
if(visited[i]==false)
{
cout<<-1<<endl;
return 0;
}
}
cout<<1<<endl;
}
106.岛屿的周长(卡码网)【打破惯性思维】
题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。
你可以假设矩阵外均被水包围。在矩阵中恰好拥有一个岛屿,假设组成岛屿的陆地边长都为 1,请计算岛屿的周长。岛屿内部没有水域。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出一个整数,表示岛屿的周长。
输入示例
5 5
0 0 0 0 0
0 1 0 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
输出示例
14
提示信息
岛屿的周长为 14。
数据范围:
1 <= M, N <= 50。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
vector<vector<int>> grid(n+1,vector<int>(m+1,0));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>grid[i][j];
int dir[4][2]={1,0,-1,0,0,-1,0,1};
int result=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(grid[i][j]==1)
{
for(int k=0;k<4;k++)
{
int nexti=i+dir[k][0];
int nextj=j+dir[k][1];
if(nexti<=0||nexti>=grid.size()||nextj<=0||nextj>=grid[1].size()||grid[nexti][nextj]==0)
result++;
}
}
}
cout<<result<<endl;
}