传送门
首先把题目给的边加入,然后对于火车来说,加入火车边有可能似的路径更短,所以说把火车的边也要加进去,那么最后看下起点到k个终点的路径的最短路是通过火车直达的还是通过其他边到达的就行了。
就是这一步,如果说火车到达v点,而起点到v点的最短路小于火车的路径,就拆掉,如果等于路径,看一下到达这个点的最短路有几条,如果有大于1条的话,那么说明还有其他最短路可以到达,那么当前的火车就可以拆掉
最短路计数,记录从起点到达这个点的路径个数
if(dis[v] == dis[u] + e[i].w) num[v]++;
else if(dis[v] > dis[u] + e[i].w) {
num[v] = 1;
dis[v] = dis[u] + e[i].w;
q.push((Node){dis[v], v});
}
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#define ll long long
const int N = 1e5 + 5;
const int M = 5e5 + 5;
const int INF = 0x3f3f3f3f;
struct Edge{
int to, next, w;
}e[M << 1];
int head[N], tot;
void add(int u, int v, int w){
e[++tot].to = v;
e[tot].w = w;
e[tot].next = head[u];
head[u] = tot;
}
int dis[N], num[N];
bool vis[N];
struct Node{
int dis, pos;
bool operator < (const Node &b) const {
return dis > b.dis;
}
};
void Dijstra(int s, int n){
for(int i = 1; i <= n; i++) dis[i] = INF;
for(int i = 1; i <= n; i++) vis[i] = 0;
dis[s] = 0;
priority_queue<Node> q;
q.push((Node){dis[s], s});
while(!q.empty()) {
Node temp = q.top(); q.pop();
int u = temp.pos;
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if(dis[v] == dis[u] + e[i].w) num[v]++;
else if(dis[v] > dis[u] + e[i].w) {
num[v] = 1;
dis[v] = dis[u] + e[i].w;
q.push((Node){dis[v], v});
}
}
}
}
int main(){
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= m; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
add(u, v, w); add(v, u, w);
}
int ans = 0;
Dijstra(1, n);
vector<int> v1, v2;
for(int i = 1; i <= k; i++) {
int x, d;
scanf("%d%d", &x, &d);
v1.push_back(x); v2.push_back(d);
add(1, x, d); add(x, 1, d);
}
Dijstra(1, n);
for(int i = 0; i < k; i++) {
int v = v1[i];
int w = v2[i];
if(dis[v] < w) ans++;
else if(dis[v] == w) {
if(num[v] > 1) {
ans++; num[v]--;
}
}
}
printf("%d
", ans);
return 0;
}