题目链接

deque优化spfa/dijkstra + 拓扑排序求DAG最短路

deque优化:比队首优的插入队首,否则插入队尾 dijkstra + 拓扑排序:dijkstra 求无向图的连通块最短路,拓扑排序求DAG的最短路(n+m)
#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <deque>
   
using namespace std;
   
typedef long long ll;
   
const int MaxnN = 250000+10;
const int MaxnM = 2e5+10;
const int INF = 0x3f3f3f3f;
   
struct Edge {
    int v, w, next;
} edge[MaxnM];
 
int h[MaxnN], edge_cnt;
int d[MaxnN], cnt[MaxnN];
int T, R, P, S;
bool vis[MaxnN];
 
void add(int u, int v, int w) {
    edge[edge_cnt].v = v;
    edge[edge_cnt].w = w;
    edge[edge_cnt].next = h[u];
    h[u] = edge_cnt++;
}
 
void spfa(int s) {
    for(int i = 1; i <= T; ++i) {
        vis[i] = false;
        cnt[i] = 0;
        d[i] = INF;
    }
    d[s] = 0; vis[s] = true;
    deque <int> qu;
    qu.push_back(s);
     
    while(!qu.empty()) {
        int u = qu.front(); qu.pop_front();
        vis[u] = false;
         
        for(int i = h[u]; i != -1; i = edge[i].next) {
            Edge &e = edge[i];
            if(d[e.v] > d[u]+e.w) {
                d[e.v] = d[u]+e.w;
                if(!vis[e.v]) {
                    vis[e.v] = true;
                    if(++cnt[e.v] > T) return;
                    if(!qu.empty()) {
                        if(d[e.v] <= d[qu.front()]) qu.push_front(e.v);
                        else qu.push_back(e.v);
                    } else qu.push_back(e.v);
                }
            }
        }
    }
}
 
int main(void)
   
{
    int u, v, w;
    scanf("%d%d%d%d", &T, &R, &P, &S);
    for(int i = 1; i <= T; ++i) h[i] = -1;
    edge_cnt = 0;
     
    for(int j = 0; j < R; ++j) {
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w); add(v, u, w); 
    }
    for(int j = 0; j < P; ++j) {
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w); 
    }
    spfa(S);
    for(int i = 1; i <= T; ++i) {
        if(d[i] == INF) puts("NO PATH");
        else printf("%d\n", d[i]);
    }
    return 0;
 }
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
 
using namespace std;
 
const int MaxnN = 25000+10;
const int MaxnM = 2e5+10;
const int INF = 0x3f3f3f3f;
 
struct Edge {
    int v, w, next;
} edge[MaxnM];
 
struct Node {
    int v, w;
    Node(int _v, int _w):v(_v), w(_w) {
    }
    bool operator < (const Node &a1) const {
        return w > a1.w;
    }
};
 
int h[MaxnN], edge_cnt, tot;
int deg[MaxnN], d[MaxnN], sccc[MaxnN]; 
int T, R, P, S;
vector <int> scc[MaxnN];
bool vis[MaxnN];
 
void add(int u, int v, int w) {
    edge[edge_cnt].v = v;
    edge[edge_cnt].w = w;
    edge[edge_cnt].next = h[u];
    h[u] = edge_cnt++;
}
 
void dfs(int u) {
    vis[u] = true;
    scc[tot].push_back(u);
    sccc[u] = tot;
     
    for(int i = h[u]; i != -1; i = edge[i].next) {
        Edge &e = edge[i];
        if(!vis[e.v]) dfs(e.v);
    }
}
 
void topsort() {
    for(int i = 1; i <= T; ++i) d[i] = INF;
    d[S] = 0; 
    queue <int> q;
    for(int i = 1; i <= tot; ++i) {
        if(!deg[i]) q.push(i);
    }
    priority_queue <Node> qu;
    while(!q.empty()) {
        int u = q.front(); q.pop();
     
        for(int i = 0; i < scc[u].size(); ++i) qu.push(Node(scc[u][i], d[scc[u][i]]));
        for(int i = 1; i <= T; ++i) vis[i] = false;
        while(!qu.empty()) {
            u = qu.top().v; qu.pop();
            if(vis[u]) continue;
            vis[u] = true;
             
            for(int i = h[u]; i != -1; i = edge[i].next) {
                Edge &e = edge[i];
                if(!vis[e.v] && d[e.v] > d[u]+e.w) {
                    d[e.v] = d[u]+e.w;
                    if(sccc[e.v] == sccc[u]) qu.push(Node(e.v, d[e.v]));
                }
                if(sccc[e.v] != sccc[u]) {
                    if(--deg[sccc[e.v]] == 0) q.push(sccc[e.v]);
                }
            }
        }
    }
}
 
int main(void)
{
    scanf("%d%d%d%d", &T, &R, &P, &S);
    for(int i = 1; i <= T; ++i) h[i] = -1, vis[i] = false;
    edge_cnt = 0;
     
    int u, v, w;
    for(int i = 0; i < R; ++i) {
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w); add(v, u, w);
    } 
    tot = 0;
    for(int i = 1; i <= T; ++i) {
        if(!vis[i]) {
            tot++; dfs(i);
            deg[tot] = 0;
        }
    }
    for(int i = 0; i < P; ++i) {
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w);
        deg[sccc[v]]++;
    }
    topsort();
    for(int i = 1; i <= T; ++i) {
        if(d[i] > 1000000000) printf("NO PATH\n"); // 不可达的点,可能会被负边松弛,取一个可行最大值作为判断条件 
        else printf("%d\n", d[i]);
    }
    return 0;
 }