题目链接
思路在于,先跑一遍最短路并记录到每一个点最短路的条数,如果铁路长度小于该点最短路,那么一定可以删除,如果等于,就要特判是否该铁路是唯一最短路。总的来说,不是很难,但是细节太重要了!!!
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll INF = 1e9;
struct node
{
ll to;
ll v;
ll next;
}edge[2000000];
struct enode
{
ll dis;
ll to;
};
struct train
{
ll to;
ll val;
}tnode[1000000];
bool operator < (const enode a,const enode b)
{
return a.dis > b.dis;
}
ll head[1000000],cnt,dis[120000],vis[120000],in[1000000];
void addedge(int a,int b,int val)
{
cnt++;
edge[cnt].next = head[a];
edge[cnt].to = b;
edge[cnt].v = val;
head[a] = cnt;
}
void dij(ll start,ll n)
{
for(int i = 1; i <= n; i++){
dis[i] = INF;
}
dis[start] = 0; in[start] = 1;
priority_queue <enode> q;
q.push(enode{0,start});
while(!q.empty()){
enode x = q.top();
q.pop();
int u = x.to;
if(vis[u]){
continue;
}
vis[u] = 1;
for(int i = head[u]; i != 0; i = edge[i].next){
if(dis[edge[i].to] == edge[i].v + dis[u]){
in[edge[i].to] += in[u];//记录最短路个数
}
if(dis[edge[i].to] > edge[i].v + dis[u]){
dis[edge[i].to] = edge[i].v + dis[u];
in[edge[i].to] = in[u];//每次更新一次最短路,就要把最短路条数更新成1
q.push(enode{dis[edge[i].to],edge[i].to});
}
}
}
}
int main()
{
ll n,m,k;
in[1] = 1;
scanf("%lld%lld%lld",&n,&m,&k);
while(m--){
ll b,e,v;
scanf("%lld%lld%lld",&e,&b,&v);
addedge(b,e,v);
addedge(e,b,v);
}
for(int i = 1; i <= k; i++){
scanf("%lld%lld",&tnode[i].to,&tnode[i].val);
addedge(1,tnode[i].to,tnode[i].val);
addedge(tnode[i].to,1,tnode[i].val);
}
dij(1,n);
//记录可删铁路的数量
int num = 0;
for(int i = 1; i <= k; i++){
ll j = tnode[i].to;
ll w = tnode[i].val;
//如果铁路长度大于最短路,那么必不可能参与最短路的组成
if(dis[j] < w){
num++;
}
//如果铁路长度等于到该点的最短路,那么就看是否为唯一的最短路
if(dis[j] == w&&in[j] != 1){
num++;
in[j]--;
}
}
printf("%d\n",num);
return 0;
}