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



京公网安备 11010502036488号