第十一章 图论

本文介绍了图论中的DFS(深度优先搜索)和BFS(广度优先搜索)算法,强调了它们在解决最短路径、连通性问题中的应用。BFS适用于找最短路径,需要使用vis数组记录已访问节点;DFS则用于判断两点间是否联通,同样需要vis数组,但可能涉及回溯。文章还提到了图的最小生成树问题、拓扑排序、二分图、欧拉路径等相关概念。
摘要由CSDN通过智能技术生成

bfs解决最短的问题,那个点到哪个点要走的最短的距离,bfs一定要写vis数组,访问过的节点要标注为1,走下一步(也就是往queue中放新节点时)一定要判断vis【】等于0,即没有访问过。

dfs呢?dfs解决分成几块,哪两个点之间是否能联通的情况。也一定要有vis数组其他过程与上述一样,但是如有回溯的需要的话,就需要在回溯时再把vis改成0

树与图的关系

1、没有圈的连通图,就是树(连通图:任意两点相连,强连通图:有向图任意两点相连)

2、没有圈的非联通图,就是森林

3、一棵树边数等于顶点数-1

4、边数等于顶点数-1的连通图就是树

有向图的术语:

没有圈的有向图叫做有向无环图,(DAG  directed acyclic graph)

邻接表的表示:

package org.lanqiao.algo.elementary._12_graph;

import java.util.ArrayList;
import java.util.List;

/*邻接表*/
public class GraphNode_AL {
  public int val;  //每一个顶点的意思
  private List<GraphNode_AL> neighbors;//邻居

  public boolean checked = false;

  public GraphNode_AL(int val) { //构造器
    this.val = val;
  }

  public GraphNode_AL getNeighbor(int i) {  //访问器,给他一个邻居的编号,返回邻居
    return neighbors.get(i);
  }

  public void add(GraphNode_AL node) {  //更改器,传一个邻居进来
    if (this.neighbors == null)   this.neighbors = new ArrayList<>();
    
    this.neighbors.add(node);
  }

  public int size() {
    return this.neighbors.size();
  }
}
package org.lanqiao.algo.elementary._12_graph.dfs;

import org.lanqiao.algo.elementary._12_graph.GraphNode_AL;

/*邻接表来表示图*/
public class Graph {
  public static void main(String[] args) {
    GraphNode_AL n1 = new GraphNode_AL(1);
    GraphNode_AL n2 = new GraphNode_AL(2);
    GraphNode_AL n3 = new GraphNode_AL(3);
    GraphNode_AL n4 = new GraphNode_AL(4);
    GraphNode_AL n5 = new GraphNode_AL(5);
    GraphNode_AL n6 = new GraphNode_AL(6);
    GraphNode_AL n7 = new GraphNode_AL(7);
    GraphNode_AL n8 = new GraphNode_AL(8);
    GraphNode_AL n9 = new GraphNode_AL(9);

    n1.add(n2);
    n1.add(n3);
    n1.add(n7);
    n1.add(n8);
    n1.add(n9);

    n2.add(n1);
    n2.add(n5);

    n3.add(n1);
    n3.add(n5);
    n3.add(n6);

    n4.add(n1);
    n4.add(n6);
    n5.add(n2);
    n5.add(n3);
    n6.add(n3);
    n6.add(n4);
    n7.add(n1);
    n8.add(n1);
    n9.add(n1);

    dfs(n9);


  }

  static void dfs(GraphNode_AL node) {
    System.out.println(node.val);
    node.checked = true;
    for (int i = 0; i < node.size(); i++) {
      GraphNode_AL graphNode = node.getNeighbor(i);
      if (graphNode.checked == false)
        dfs(graphNode);
    }
  }
}

 

边集的表示

package org.lanqiao.algo.elementary._12_graph;

/**
 * 边 的封装
 * 边集可以用来表示图
 */
public class Edge<T> implements Comparable<Edge> {
  private T start;
  private T end;
  private int distance;

  public Edge(T start, T end, int distance) {
    this.start = start;
    this.end = end;
    this.distance = distance;
  }

  public T getStart() {
    return start;
  }

  public void setStart(T start) {
    this.start = start;
  }

  public T getEnd() {
    return end;
  }

  public void setEnd(T end) {
    this.end = end;
  }

  public int getDistance() {
    return distance;
  }

  public void setDistance(int distance) {
    this.distance = distance;
  }

  @Override
  public String toString() {
    return start + "->" + end + ":" + distance;
  }

  @Override
  public int compareTo(Edge obj) {
    int targetDis = obj.getDistance();
    return distance > targetDis ? 1 : (distance == targetDis ? 0 : -1);
  }
}
package org.lanqiao.algo.elementary._12_graph;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MapBuilder {
  public List<Edge> build() {
    List<Edge> edges = new ArrayList<>();
    edges.add(new Edge("1", "2", 4));
    edges.add(new Edge("1", "3", -1));
    edges.add(new Edge("2", "3", 3));
    edges.add(new Edge("2", "4", 5));
    edges.add(new Edge("4", "5", 10));
    // Collections.sort(edges);
    return edges;
  }

  public int getPointNum() {
    return 5;
  }

  public List<Edge> build1() {
    List<Edge> edges = new ArrayList<>();
    edges.add(new Edge("1", "2", 4));
    edges.add(new Edge("1", "3", -1));
    edges.add(new Edge("2", "3", 3));
    edges.add(new Edge("2", "4", 5));
    edges.add(new Edge("4", "5", 10));
    edges.add(new Edge("0", "2", 10));
    edges.add(new Edge("0", "3", 10));
    edges.add(new Edge("0", "4", 1));
    edges.add(new Edge("0", "5", 1));

    Collections.sort(edges);
    return edges;
  }

  public int getPointNum1() {
    return 6;
  }
}

2、图的dfs

/*给定一个方阵,定义连通:上下左右相邻,并且值相同。
可以想象成一张地图,不同的区域被涂以不同颜色。
输入:
整数N, (N<50)表示矩阵的行列数
接下来N行,每行N个字符,代表方阵中的元素
接下来一个整数M,(M<1000)表示询问数
接下来M行,每行代表一个询问,
格式为4个整数,y1,x1,y2,x2,
表示询问(第y1行,第x1列) 与 (第y2行,第x2列) 是否连通。
连通输出true,否则false

例如:
10
0010000000
0011100000
0000111110
0001100010
1111010010
0000010010
0000010011
0111111000
0000010000
0000000000
3
0 0 9 9
0 2 6 8
4 4 4 6

程序应该输出:
false
true
true*/

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        char[][] graph =    new char[N][N];
        for(int i=0;i<N;i++){
            graph[i] = sc.nextLine().toCharArray();
        }
        int M =sc.nextInt();
        int[][] query = new int[M][4];
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < 4; j++) {
                query[i][j] = sc.nextInt();
            }
        }
        // M个起点和终点
        for (int i = 0; i < M; i++) {
            //对每个起点和终点,检查是否连通
            boolean ok_fal = check(graph, new int[N][N], query[i]);//一个例子一个例子查
            System.out.println(ok_fal);
        }

    }
    static boolean check(char[][] graph, int[][] label, int[] points){
        int x1 = points[0];
        int y1 = points[1];
        int x2 = points[2];
        int y2 = points[3];

        if(x1 ==x2 && y1 ==y2){
            return true;
        }

        int value = graph[x1][y1];
        boolean f1 = false;
        boolean f2 = false;
        boolean f3 = false;
        boolean f4 = false;

        //往左走
        if(x1-1>=0 && label[x1-1][y1]==0 &&graph[x1 - 1][y1] == value){
            label[x1 - 1][y1] = 1; // 坐标的位置标记为已访问
            points[0] = x1 - 1; // 把左边的点作为新起点,递归
            f1 = check(graph, label, points);
            //回溯
            label[x1 - 1][y1] = 0;
            points[0] = x1;
        }
        //往右走
        if (x1 + 1 < graph.length && label[x1 + 1][y1] == 0 && graph[x1 + 1][y1] == value) {
            label[x1 + 1][y1] = 1;
            points[0] = x1 + 1;
            f2 = check(graph, label, points);
            label[x1 + 1][y1] = 0;
            points[0] = x1;
        }
        //往上走
        if (y1 - 1 >= 0 && label[x1][y1 - 1] == 0 && graph[x1][y1 - 1] == value) {
            label[x1][y1 - 1] = 1;
            points[1] = y1 - 1;
            f3 = check(graph, label, points);
            label[x1][y1 - 1] = 0;
            points[1] = y1;
        }
        //往下走
        if (y1 + 1 < graph.length && label[x1][y1 + 1] == 0 && graph[x1][y1 + 1] == value) {
            label[x1][y1 + 1] = 1;
            points[1] = y1 + 1;
            f4 = check(graph, label, points);
            label[x1][y1 + 1] = 0;
            points[1] = y1;
        }
        return f1|| f2 || f3 || f4;
        //若有一个可以,那就可行

    }

}

2、/**
 * 输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。
 *  如果两个字符“@”所在的格子相邻(横、竖或者对角线方向),就说它们属于同一个八连块。
 *
 *  分析:图的dfs
 */

public class Main{
    static char[][] data = {
            "*@@*@".toCharArray(),
            "**@*@".toCharArray(),
            "****@".toCharArray(),
            "@@@*@".toCharArray(),
            "@@**@".toCharArray(),
    };
    static int cnt;
    static void dfs(int r,int c){
        if(r<0 || r>=data.length || c<0 ||c>=data.length) return; //超出范围
        if( data[r][c] == '*'){
            return;
        }
        data[r][c] ='*';
        dfs(r+1,c);
        dfs(r-1,c);
        dfs(r, c + 1);
        dfs(r, c - 1);
        dfs(r + 1, c + 1);
        dfs(r + 1, c - 1);
        dfs(r - 1, c - 1);
        dfs(r - 1, c + 1);
    }

    public static void main(String[] args) {
        for(int i=0;i<data.length;i++){
            for(int j=0;j<data[0].length;j++){
                if(dat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值