leetcode里和graph相关的题目根据解题思路可以分成以下几个大类:

  1. Depth First Search
    典型题型:求具体路径
    有一类题型很常见也很重要:给你一张图,一个起始点(起始状态),一个终止状态(终止状态)让你求路径的,最典型的是走迷宫的问题。(这是我目前比较薄弱的一块)
  2. Breadth First Search
    典型题型:求最短距离
    这两天做了两道求全局最短距离的题目(边的权重均为1),同样用bfs,但由于要访问每一个节点,可能需要走走回头路。这个时候visited数组就不再是记录每个点的访问情况了,而要记录的是一种状态:目前所处的位置+所有节点的访问情况,也就是说每种状态只能出现一次。
    以864、Shortest Path to Get All Keys为例,visited数组存放的是(x, y, status),x、y分别是目前所处位置的横纵坐标,status记录的是每把钥匙获取的情况(用二进制数来处理)。
  3. Topological Sort
    典型题型:node之间有先后顺序,需要判断图中是否存在有向环
  4. Union Find
    典型题型:节点之间相互连接,求group的个数等等

有些题目的关键是如何建图,两种建图形式:

  1. 邻接矩阵:
    例:int[][] graph = new intn;
  2. 邻接列表:
    例:List<int[]>[] graph = new List[n];
    HashMap<Integer, HashMap<Integer, Integer>> graph = new HashMap<>();

图的题目给我们的常常是这三种形式:

  1. 二维数组,每个格子就是每个node,这种情况就不需要我们建图了,每个格子周围的四个方向就是它的连接点(在没有其他限制的条件下)
  2. 给出边的形式(u,v,w):这是一条两端点为u、v权重为w的边。我们需要把所有给出的边建立graph,用邻接矩阵或是邻接列表都可以。另外注意一下是directed的还是undirected的
  3. 给出一个二维数组,例如[[1,2],[0,1],[2]],ai表示和i和j相连,也就是a[i]存储是i点的连接点,这种情况下一般我们也不需要建图

求最短路径:

  1. Dijkstra
    Dijkstra的两种写法:
    以leetcode 743为例:
    一、把除了起始点以外的其他点到起始点的距离设为0,也是最常规的写法。
class Solution {
    public int networkDelayTime(int[][] times, int N, int K) {
        List<int[]>[] graph = new List[N+1];
        for (int i = 1; i <= N; i ++)
            graph[i] = new ArrayList<>();
        for (int[] time : times) 
            graph[time[0]].add(new int[] {time[1], time[2]});
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b)->Integer.compare(a[1], b[1]));
        int[] dist = new int[N+1];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[K] = 0;
        pq.offer(new int[] {K, 0});
        int max = 0;
        while (!pq.isEmpty()) {
            int[] node = pq.poll();
            int u = node[0];
            max = Math.max(max, dist[u]);
            for (int[] edge : graph[u]) {
                int v = edge[0];
                int d = edge[1];
                if (dist[u]+d < dist[v]) {
                    dist[v] = dist[u]+d;
                    pq.offer(new int[] {v, dist[v]});
                }
            }
        }
        for (int i = 1; i <= N; i ++)
            if (dist[i] == Integer.MAX_VALUE)
                return -1;
        return max;
    }
}
二、不需要初始化为INF
class Solution {
    public int networkDelayTime(int[][] times, int N, int K) {
        boolean[] used = new boolean[N+1];
        int[][] graph = new int[N+1][N+1];
        for (int i = 1; i <= N; i ++) {
            for (int j = 1; j <= N; j ++)
                graph[i][j] = -1;
        }
        for (int[] time : times) 
            graph[time[0]][time[1]] = time[2];
        PriorityQueue<int[]> pq = new PriorityQueue<>((a,b)->Integer.compare(a[1], b[1]));
        pq.offer(new int[] {K, 0});
        int max = 0;
        while (!pq.isEmpty()) {
            int[] edge = pq.poll();
            int u = edge[0];
            int d = edge[1];
            if (used[u])    continue;
            used[u] = true;
            max = Math.max(max, d);
            for (int i = 1; i <= N; i ++) {
                if (graph[u][i] == -1) continue;
                pq.offer(new int[] {i,d+graph[u][i]});
            }
        }
        for (int i = 1; i <= N; i ++)
            if (!used[i])   return -1;
        return max;
    }
}
  1. Bellman-Ford:

我想做个正常人
1 声望2 粉丝