题目链接
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;
}