算法题——图论

98.可达路径

使用深度优先遍历进行递归

邻接矩阵存储,进行深度优先遍历

java 复制代码
import java.util.*;
 
public class Main{
    static List<List<Integer>> res = new ArrayList<>();
 
    static List<Integer> path = new ArrayList<>(); 
 
    public static void dfs(int[][] graph, int cur, int target){
        if(cur==target){  //如果当前遍历的就是目标节点,则说明找到了一条路径
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=1;i<=target;i++){ //遍历当前节点对应的邻接矩阵的一行,与当前节点相连的节点可以加入路径
            if(graph[cur][i]==1){
                path.add(i);
                dfs(graph, i, target);
                path.remove(path.size()-1);
            }
        }
    }
 
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
 
        int[][] graph = new int[n+1][n+1]; //定义邻接矩阵
        while(m--!=0){
            int s = sc.nextInt();
            int t = sc.nextInt();
            graph[s][t] = 1;  //对应边的位置
        }
        path.add(1);  ////题目要求从1开始,所以path第一个元素必须是
        dfs(graph, 1, n);
 
        if(res.isEmpty()) System.out.println(-1); //处理输出
        for(List<Integer> list : res){
            for(int i=0;i<list.size()-1;i++){
                System.out.print(list.get(i) + " ");
            }
            System.out.println(list.get(list.size()-1));
        }
    }
}

邻接表存储,进行深度优先遍历

java 复制代码
import java.util.*;

public class Main {
    static List<List<Integer>> res = new ArrayList<>();
    static List<Integer> path = new ArrayList<>();

    static void dfs(List<LinkedList<Integer>> graph, int cur, int target) {
        if (cur == target) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i : graph.get(cur)) { //遍历当前节点对应的链表,链表上的节点可以加入路径
            path.add(i);
            dfs(graph, i, target);
            path.remove(path.size() - 1);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        List<LinkedList<Integer>> graph = new ArrayList<>(n + 1);//定义邻接表
        for(int i=0;i<=n;i++){  //初始化邻接表的边表(链表)
            graph.add(new LinkedList<Integer>());
        }
        while (m-- > 0) {
            int s = sc.nextInt();
            int t = sc.nextInt();
            graph.get(s).add(t); //将边的信息加入邻接表
        }
        path.add(1); //题目要求从1开始,所以path第一个元素必须是1
        dfs(graph, 1, n);
        if (res.isEmpty()) System.out.println(-1); //处理输出
        for (List<Integer> list : res) {
            for (int i = 0; i < list.size() - 1; i++) {
                System.out.print(list.get(i) + " ");
            }
            System.out.println(list.get(list.size() - 1));
        }
    }
}

要熟悉邻接矩阵和邻接表存储图的过程,熟悉dfs遍历的写法

99.计数孤岛

本题思路是用遇到一个没有遍历过的节点陆地,计数器就加一,然后把该节点陆地所能遍历到的陆地都标记上。

在遇到标记过的陆地节点海洋节点的时候直接跳过。 这样计数器就是最终岛屿的数量

深度优先遍历的写法:

java 复制代码
import java.util.*;

public class Main{
    public static int[][] dir = {{0,-1}, {0,1}, {-1,0}, {1,0}}; //四个方向
    public static void dfs(boolean[][] visited, int[][] graph, int x, int y){
        //获取四个方向的坐标
        for(int i=0;i<4;i++){
            int nextX = x+dir[i][0];
            int nextY = y+dir[i][1];
            if(nextX<0 || nextY<0 || nextX>=graph.length || nextY>=graph[0].length) continue;
            if(!visited[nextX][nextY] && graph[nextX][nextY]==1){
                //该位置未被访问过,且为陆地
                visited[nextX][nextY] = true;
                dfs(visited, graph, nextX, nextY);
            }
        }
    }
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[][] graph = new int[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                graph[i][j] = sc.nextInt();
            }
        }
        boolean[][] visited = new boolean[n][m];
        int res = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(!visited[i][j] && graph[i][j]==1){
                    visited[i][j]=true;
                    res++; 
                    dfs(visited, graph, i, j);
                }
            }
        }
        System.out.println(res);
     }
}

广度优先遍历需要定义一个队列,注意每把一个Pair加入队列时,都要立马让visited标记为true,避免重复遍历

java 复制代码
import java.util.*;

public class Main{
    public static int[][] dir = {{0,-1}, {0,1}, {-1,0}, {1,0}};

    public static class Pair{ //定义一个Pair类
        int first;
        int second;

        public Pair(int x, int y){
            this.first = x;
            this.second = y;
        }
    }

    public static void bfs(boolean[][] visited, int[][] graph, int x, int y){
        Queue<Pair> que = new LinkedList<>();
        que.offer(new Pair(x,y));
        visited[x][y] = true;//入队就直接标记为访问过
        while(!que.isEmpty()){
            int curX = que.peek().first;
            int curY = que.poll().second; //出队
            for(int i=0;i<4;i++){
                int nextX = curX+dir[i][0];
                int nextY = curY+dir[i][1];
                if(nextX<0 || nextY<0 || nextX>=graph.length || nextY>=graph[0].length) continue; //超出图的部分直接跳出循环
                if(!visited[nextX][nextY] && graph[nextX][nextY]==1){
                    que.offer(new Pair(nextX, nextY));
                    visited[nextX][nextY] = true;
                }
            }
        }
    }

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int[][] graph = new int[n][m];
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                graph[i][j] = sc.nextInt();
            }
        }
        boolean[][] visited = new boolean[n][m];
        int res = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(!visited[i][j] && graph[i][j]==1){
                    res++; 
                    bfs(visited, graph, i, j);
                }
            }
        }
        System.out.println(res);
     }
}
相关推荐
luj_176841 分钟前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
郝学胜-神的一滴1 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆2 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill
Water_Sunzhipeng2 小时前
2024牛客暑期多校训练营1
算法
hetao17338372 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
技术小黑2 小时前
RNN算法实战系列06 | LSTM 实现糖尿病探索与预测
rnn·算法·lstm
疯狂打码的少年2 小时前
【数据结构】二叉树的性质(五大性质+计算)
数据结构·笔记·算法
wabs6663 小时前
关于图论【A*算法 | 卡码网127.骑士的攻击的思考】
数据结构·算法·图论·卡码网·广搜的改进版
CIO_Alliance3 小时前
AI认知系列(3)| 数据、算法、算力、场景四要素协同
人工智能·算法·ipaas·系统集成·企业cio联盟·企业级ai化转型
..Dauntless..4 小时前
手写vector vs std::vector:从功能正确到性能达标
算法