My questions about SPFA time complexity

Revision en3, by b06b01073, 2021-02-24 04:46:25

Hello codeforces community, I recently run in to a problem D. Okabe and City, someone use shortest path algorithm to solve this problem, which is SPFA to be more specifically.

And here is the code from https://blog.csdn.net/lyg_air/article/details/77163091.

#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
 
#define LL long long
#define INF 0x3f3f3f3f
 
using namespace std;
const int MX = 1e4 + 5;
int n, m, k;
struct node{
    int x, y;
}lit[MX];
int dis[MX];
int inq[MX];
 
int spfa(){
    for(int i = 1; i <= k; i++){
        dis[i] = INF;
    }
    queue<int> q;
    q.push(1);
    inq[1] = 1;
    dis[1] = 0;
    while(!q.empty()){
        int u = q.front();
        q.pop();
        inq[u] = 0;
        for(int i = 1; i <= k; i++){
            if(u == i)  continue;
            int val = INF;
            int dx = abs(lit[u].x - lit[i].x);
            int dy = abs(lit[u].y - lit[i].y);
            if(dx+dy == 1){
                val = 0;
            }
            else if(dx <= 2 || dy <= 2){
                val = 1;
            }
            if(dis[i] > dis[u] + val){
                dis[i] = dis[u] + val;
                if(!inq[i]){
                    q.push(i);
                    inq[i] = 1;
                }
            }
        }
    }
    if(dis[k] != INF)   return dis[k];
    return -1;
}
 
 
int main(){
    scanf("%d%d%d", &n, &m, &k);
    int flag = 0;
    for(int i = 1; i <= k; i++){
        int u, v;
        scanf("%d%d", &lit[i].x, &lit[i].y);
        if(lit[i].x == n && lit[i].y == m)  flag = 1;
    }
    if(!flag){
        lit[++k].x = n+1;
        lit[k].y = m+1;
    }
    cout << spfa() << endl;
    return 0;
}

In this code, it treats all the initially lit positions as a vertice and try to calculate the shortest path to the bottom-right corner using SPFA.

The worst case of SPFA is $$$O(|V||E|)$$$ according to wiki, and in the for loop inside the spfa function, it seems this code treat the graph as a complete graph(since for every vertice pop from the queue, it consider all other $$$k - 1$$$ vertices, where $$$k$$$ is the number of vertices), which make $$$O(|E|) = O(|V|^2)$$$, and the overall time complexity will turn into $$$O(|V|^3)$$$.

In this problem, $$$k \leq 10^4$$$, which doesn't look promising for a 4 seconds time limit, however this code only take 529ms in this submission(the code is the same as above) and get accepted.

My questions are,

  1. Am I misunderstand SPFA?

  2. my analysis of the $$$O(|V|^3)$$$ time complexity is totally wrong

Please let me know if my question is unclear, and thanks for all your help :)

Tags spfa

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en4 English b06b01073 2021-02-24 11:05:22 6
en3 English b06b01073 2021-02-24 04:46:25 4
en2 English b06b01073 2021-02-24 04:46:03 1 Tiny change: 'are,\n\n1.. Am I mis' -> 'are,\n\n1. Am I mis' (published)
en1 English b06b01073 2021-02-24 04:44:37 3077 Initial revision (saved to drafts)