Understanding of dijestra algorithm and its proof by counter proof method

Posted by XtacY on Tue, 04 Jan 2022 08:59:09 +0100

Understanding of dijestra algorithm

Today, do a single source longest path problem leetcode-743 , although I immediately thought of dijestra algorithm, I became a little vague about its specific idea, so I reviewed this classic algorithm with this problem.

  • Overview of dijestra algorithm
    Dijkstra algorithm was proposed by Dutch computer scientist Dijkstra in 1959, so it is also called Dijkstra algorithm. It is the shortest path algorithm from one vertex to other vertices, which solves the shortest path problem in weighted graph. The main feature of dijestra algorithm is that it starts from the starting point and adopts the strategy of greedy algorithm. Each time it traverses the adjacent nodes of the vertices closest to the starting point and not visited until it extends to the end point.
  • Personal understanding
    Suppose there are n nodes (V1, V2, V3,..., Vn) and the starting node is V1. In the implementation process, three arrays need to be maintained, one is dist [], that is, the distance between each node and V1; used [] indicates whether the node has been found the shortest path; path [], that is, the source node reaching the node.
    The idea of the algorithm is embodied in the specific process, that is, the process of successively finding the first, second, third and Nth closest to V1, that is, adding the nodes of the array used [] in turn. Array visited [] every time a new node is added, the dist [] and path [] must be updated to prepare for finding the next near node.
    The following is the implementation code of leetcode 743. I wrote a lot of comments and hope that the readability can meet the needs of most visitors. Because leetcode 743 does not require a path, the array is not maintained in the code. You only need to look at the part of dijestra's implementation.
class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        final int INF = Integer.MAX_VALUE / 2;
        int[][] g = new int[n][n];
        // Initialize adjacency matrix
        for (int i = 0; i < n; ++i) {
            Arrays.fill(g[i], INF);
        }
        for (int[] t : times) {
            int x = t[0] - 1, y = t[1] - 1;
            g[x][y] = t[2];
        }

        int[] dist = new int[n];
        Arrays.fill(dist, INF);
        dist[k - 1] = 0;
        boolean[] used = new boolean[n];
        //-------------------------Split line---------------------
        // dijkstra algorithm can be seen from here
        /**
        Each outer loop will execute once, used[x] = true; It is equivalent to adding a node i closest to the starting node in the array.
        After adding nodes, you need to update the dist array. Prepare for finding the I + 1st node.
        */ 
        for (int i = 0; i < n; ++i) {
            int x = -1;
            int dmin = INF;
            /**
            The inner loop is to find the node with the smallest dist among the nodes whose used is not set to true, that is, the node closest to the starting node in the current node that is not set to true,
            That is, the node i closest to the starting node
            */ 
            for (int y = 0; y < n; ++y) {
                if (!used[y] && (dist[y] < dmin)) {
                    dmin = dist[y];
                    x = y;
                }
            }
            // If the used is not true, that is, the nodes closest to the starting node from the first to the n-1 have been found, it is over and break directly
            if(x == -1) break;
            used[x] = true;
            // The "accessibility" of the starting node is improved, and the dist array needs to be updated to prepare for finding the next nearby node in the next cycle.
            for (int y = 0; y < n; ++y) {
                dist[y] = Math.min(dist[y], dist[x] + g[x][y]);
            }
        }
        //-------------------------Split line---------------------

        int ans = -1;
        for(int i = 0; i < n; i++){
            if(dist[i] > ans){
                ans = dist[i];
            }
        }
        if(ans == INF){
            return -1;
        }else{
            return ans;
        }
    }
}

Proof by counter evidence

Let a be the point containing V1 and the shortest distance obtained, and B be the complement of A. What we need to prove now is:

Select the shortest distance from V1 to the remaining points obtained last time and set it as Vn. This distance (i.e. V1Vn) is the shortest path from V0 to Vn in all paths. In fact, it is also the next (i.e. except the midpoint of A), that is, the node closest to V1 n.

Proof: it only needs to be proved that the last transfer station from V1 to Vn must be in A.

Counter proof method: if this point is set as Vn-1 in B, it means that V1Vn-1 + vn-1vn < V1Vn at this time. In that case, it means that V1Vn-1 < V1Vn, which means that Vn-1 must be in A, because the points shorter than the next minimum distance V1Vn required at this time are in A, and the assumption is in B, so the contradiction is proved.
[note]: 1, 2, 3,..., n above. It is not the sequence number of the node in the directed graph. Instead, add the sequence number of set A. It reflects the distance from the starting node V1.

Topics: Java leetcode dijkstra