day52 图论章节刷题Part04(110.字符串接龙、105.有向图的完全可达性、106.岛屿的周长 )
广搜和深搜的提高
110.字符串接龙
思路:判断点与点之间的关系,如果差一个字符,那就是有链接;求起点和终点的最短路径长度,无向图求最短路广搜最合适,只要搜到了终点一定是最短的路径。因为广搜就是以起点中心向四周扩散的搜索。
注意:
- 本题是一个无向图,需要用标记位标记节点是否走过,否则就会死循环!
- 使用set来检查字符串是否出现在字符串集合里更快一些
代码如下:
import java.util.*;
public class Main{
public static int ladderLength(String beginStr,String endStr,List<String> wordList){
HashSet<String> set=new HashSet<>(wordList);
//队列存放访问过的单词,BFS
Queue<String> queue=new LinkedList<>();
//存放已经访问过的单词
HashMap<String,Integer> visitMap=new HashMap<>();
queue.offer(beginStr);
visitMap.put(beginStr,1);
while(!queue.isEmpty()){
String curWord=queue.poll();
int path=visitMap.get(curWord);
for(int i=0;i<curWord.length();i++){
char[] ch=curWord.toCharArray();
for(char k='a';k<='z';k++){
ch[i]=k;
String newWord=new String(ch);
//终止条件
if(newWord.equals(endStr)) return path+1;
if(set.contains(newWord)&&!visitMap.containsKey(newWord)){
visitMap.put(newWord,path+1);
queue.offer(newWord);
}
}
}
}
return 0;
}
public static void main (String[] args) {
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();
scan.nextLine();
String[] str=scan.nextLine().split(" ");
List<String> wordList=new ArrayList<>();
for(int i=0;i<n;i++){
wordList.add(scan.nextLine());
}
int result=ladderLength(str[0],str[1],wordList);
System.out.println(result);
}
}
105.有向图的完全可达性
思路:有向图搜索全路径的问题。DFS、BFS均可,一般都可以的时候我习惯使用DFS。该题是说从节点1能否到达所有节点,所以只需要从节点1开始DFS遍历,如果最后所有点都被访问过了输出1,否则-1.
可以选用邻接表或者邻接矩阵来存储数据。
代码如下:
import java.util.*;
public class Main{
public static List<List<Integer>> adjList=new LinkedList<>();
public static void dfs(boolean[] visited,int key){
if(visited[key]) return;
visited[key]=true;
List<Integer> nextKeys=adjList.get(key);
for(int nextKey:nextKeys){
dfs(visited,nextKey);
}
}
public static void main (String[] args) {
Scanner scan=new Scanner(System.in);
int vertexNum=scan.nextInt();
int edgeNum=scan.nextInt();
for(int i=0;i<vertexNum;i++){
adjList.add(new LinkedList<>());
}
for(int i=0;i<edgeNum;i++){
int s=scan.nextInt();
int t=scan.nextInt();
adjList.get(s-1).add(t-1);
}
boolean[] visited=new boolean[vertexNum];
dfs(visited,0);
for(int i=0;i<vertexNum;i++){
if(!visited[i]) {
System.out.println(-1);
return;
}
}
System.out.println(1);;
}
}
106.岛屿的周长
思路:避免看到岛屿就DFS或者BFS的惯性思维,该题不需要也可以做。
计算出总的岛屿数量,总的边数=岛屿数量 * 4,有一对相邻两个陆地,边的总数就要减2。
代码如下:
import java.util.*;
public class Main{
public static void main (String[] args) {
Scanner scan=new Scanner(System.in);
int m=scan.nextInt();
int n=scan.nextInt();
int[][] graph=new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
graph[i][j]=scan.nextInt();
}
}
int num=0;
int cover=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(graph[i][j]==1){
num++;
if(i-1>=0 && graph[i-1][j]==1) cover++;
if(j-1>=0 && graph[i][j-1]==1) cover++;
}
}
}
int result=num*4-2*cover;
System.out.println(result);
}
}