[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=4093
[算法]
对于k个枢纽 , 分别在正向图和反向图上跑dijkstra最短路 , 即可
时间复杂度 : O(K(N + M) log N)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 20010 #define MAXK 210 typedef long long LL; const LL inf = 1e15; int n , m , k , q , tot; int heada[MAXN] , headb[MAXN]; LL dist1[MAXK][MAXN] , dist2[MAXK][MAXN]; bool visited[MAXK][MAXN]; struct edge { int to , w , nxt; } e[MAXN << 2]; template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedgea(int u , int v , int w) { tot++; e[tot] = (edge){v , w , heada[u]}; heada[u] = tot; } inline void addedgeb(int u , int v , int w) { tot++; e[tot] = (edge){v , w , headb[u]}; headb[u] = tot; } inline void dijkstra1(int idx,int s) { priority_queue< pair<int,int> > q; for (int i = 1; i <= n; i++) dist1[idx][i] = inf; dist1[idx][s] = 0; q.push(make_pair(0 , s)); while (!q.empty()) { int cur = q.top().second; q.pop(); if (visited[idx][cur]) continue; visited[idx][cur] = true; for (int i = heada[cur]; i; i = e[i].nxt) { int v = e[i].to , w = e[i].w; if (dist1[idx][cur] + w < dist1[idx][v]) { dist1[idx][v] = dist1[idx][cur] + w; q.push(make_pair(-dist1[idx][v] , v)); } } } } inline void dijkstra2(int idx,int s) { priority_queue< pair<int,int> > q; for (int i = 1; i <= n; i++) dist2[idx][i] = inf; dist2[idx][s] = 0; q.push(make_pair(0 , s)); while (!q.empty()) { int cur = q.top().second; q.pop(); if (visited[idx][cur]) continue; visited[idx][cur] = true; for (int i = headb[cur]; i; i = e[i].nxt) { int v = e[i].to , w = e[i].w; if (dist2[idx][cur] + w < dist2[idx][v]) { dist2[idx][v] = dist2[idx][cur] + w; q.push(make_pair(-dist2[idx][v] , v)); } } } } int main() { read(n); read(m); read(k); read(q); for (int i = 1; i <= m; i++) { int u , v , w; read(u); read(v); read(w); addedgea(u , v , w); addedgeb(v , u , w); } for (int i = 1; i <= k; i++) { int x; read(x); memset(visited[i] , false , sizeof(visited[i])); dijkstra1(i , x); memset(visited[i] , false , sizeof(visited[i])); dijkstra2(i , x); } int ans1 = 0 , ans2 = 0; while (q--) { int x , y; read(x); read(y); LL tmp = inf; for (int i = 1; i <= k; i++) chkmin(tmp , 1LL * dist2[i][x] + 1LL * dist1[i][y]); if (tmp != inf) { ++ans1; ans2 += (LL)tmp; } } printf("%d\n%d\n" , ans1 , ans2); return 0; }