题意:给你一张无向连通图和一个起点 ,求图上到 的最短路等于 的位置的数量
这里"位置"的定义可以在点上,也可以在边上
,保证题目所给的数都是整数
显然我们把每条边拆成 条长度为 的边复杂度是爆炸了的
那对于我们求出了所有点的单源最短路后,我们可以枚举每条边,直接计算该边上有没有点满足条件
可以根据边的两个端点到 的最短路求出该边上符合条件的点的数量
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define mp(x,y) make_pair(x,y)
using namespace std;
const int N=500010;
struct EDGE{
int ver,nxt,dis,pre;
}edge[N];
int n,m,s,head[N],cnt,vis[N],dis[N];
inline int read(){
int sym=0,res=0;char ch=0;
while (!isdigit(ch))sym|=(ch=='-'),ch=getchar();
while (isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return sym?-res:res;
}
void file(){
freopen("read.in","r",stdin);
freopen("write.out","w",stdout);
}
void add(int u,int v,int t){
edge[++cnt].ver=v;
edge[cnt].pre=u;
edge[cnt].nxt=head[u];
edge[cnt].dis=t;
head[u]=cnt;
}
int main(){
n=read();m=read();s=read();
for (int i=1;i<=m;i++){
int x=read(),y=read(),t=read();
add(x,y,t);add(y,x,t);
}
priority_queue<pair<int,int> >q;q.push(mp(0,s));
memset(dis,0x3f,sizeof(dis));dis[s]=0;
while (!q.empty()){
int u=q.top().second;q.pop();
if (vis[u])continue;vis[u]=1;
for (int i=head[u];i;i=edge[i].nxt){
int v=edge[i].ver;
if (dis[v]>edge[i].dis+dis[u]){
dis[v]=edge[i].dis+dis[u];
q.push(mp(-dis[v],v));
}
}
}int ans=0,l=read();
for (int i=1;i<=n;i++){
if (dis[i]==l)ans++;
}
for (int i=1;i<=cnt;i+=2){
int u1=edge[i].pre,u2=edge[i].ver;
int d1=l-dis[u1],d2=l-dis[u2];
if (d1>0&&d1<edge[i].dis&&dis[u1]+d1<=dis[u2]+edge[i].dis-d1)ans++;
if (d2>0&&d2<edge[i].dis&&dis[u2]+d2<=dis[u1]+edge[i].dis-d2)ans++;
if (d1>0&&d2>0&&d1+d2==edge[i].dis)ans--;
}printf("%d",ans);
return 0;
}