[Dijkstra]
给你个点和条双向边,然后又给你条从双向计划道路。这一共边构成的图中:设从到每一个点的最短距离为,现在最多可以删除多少条计划道路,使得删除后的图中从到每一个点的最短距离仍然为
例如一条双向计划道路为[1,v,w],表示的双向计划道路的权值为,如何判断这一条计划道路能否可以删除呢?
  1. 如果dist[v]<w,那么这条计划道路就可以删除,因为在图中最短距离小于直接到的最短距离,那么这条边肯定可以删除
  2. 如果dist[v]=w,那么最短距离虽然等于直接到的距离,但是有可能是,其他从路径的长度构成了最短距离。那么如果存在的路径满足,那么这条计划道路就是可以删除的
做法是先用求出边构成的图中从到每个点的距离,然后判断即可

总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;

const int N = 1e5 + 10;

int n, m, k;

vector<pair<int, int> > adj[N], adj1[N];
int dist[N];
bool vis[N];


struct cmp{
    bool operator() (const pair<int, int> a, const pair<int, int> b){
        return a.second > b.second;
    }
};

void dijkstra(){
    memset(dist, 0x3f3f3f3f, sizeof(dist));
    dist[1] = 0;
    priority_queue<pair<int, int>, vector<pair<int, int> >, cmp> q;
    q.push({1, 0});
    while(q.size()){
        pair<int, int> now = q.top();
        q.pop();
        int u = now.first, ndist = now.second;
        if(vis[u]) continue;
        vis[u] = true;
        for(auto [v, w] : adj[u]){
            if(!vis[v] && dist[v] > dist[u] + w){
                dist[v] = dist[u] + w;
                q.push({v, dist[v]});
            }
        }
    }
}

signed main(){
    HelloWorld;
    
    cin >> n >> m >> k;
    for(int i = 1; i <= m; i ++){
        int u, v, w; cin >> u >> v >> w;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
        adj1[u].push_back({v, w});
        adj1[v].push_back({u, w});
    }
    vector<pair<int, int> > a(k + 1);
    for(int i = 1; i <= k; i ++){
        int v, w; cin >> v >> w;
        a[i] = {v, w};
        adj[1].push_back({v, w});
        adj[v].push_back({1, w});
    }

    dijkstra();
    int ans = 0;
    for(int i = 1; i <= k; i ++){
        int v = a[i].first, w = a[i].second;
        if(dist[v] < w) ans ++;
        else if(dist[v] == w){
            for(auto [u, w] : adj1[v]){
                if(dist[u] + w == dist[v]){
                    ans ++;
                    break;
                }
            }
        }
    }
    cout << ans << endl;
    return 0;
}