题目大意:
给出一个图,一个源点s,问距离这个源点的最短距离恰好为 l 的点有多少个(这个点可以在边上,可以在节点上)。
做法:
首先用dijkstra算法求出每个节点到s的最短路d[]数组,然后对于每条边w(u,v)来说有下面三种情况是合法的:
1:d[u]<l && l-d[u]<w(u,v) && d[v]+w(u,v)-(l-d[u])>l
2:d[v]<l && l-d[v]<w(u,v) && d[u]+w(u,v)-(l-d[v])>l
3:d[v]<l && d[u]<l && d[u]+d[v]+w(u,v)==2*l
对于上面每种情况,ans++,另外每个d[i]==l 的情况也要ans++;
代码:
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <climits>
#include <algorithm>
#define N 100010
const int INF=INT_MAX;
using namespace std;
struct edge
{
int from,to,c;
edge(int a,int b)
{
to=a,c=b;
}
edge()
{
from=0,to=0,c=0;
}
};
edge e[N];
typedef pair<int,int> p;
int V;
vector <edge> G[N*2];
int d[N];
void dijkstra(int s)
{
priority_queue<p,vector<p>,greater<p> > que;
fill(d+1,d+V+1,INF);
d[s]=0;
que.push(p(0,s));
while(!que.empty())
{
p pp=que.top();que.pop();
int v=pp.second;
if(d[v]<pp.first) continue;
for(int i=0;i<G[v].size();i++){
edge e=G[v][i];
if(d[e.to]>d[v]+e.c)
{
d[e.to]=d[v]+e.c;
que.push(p(d[e.to],e.to));
}
}
}
}
int main()
{
int m,l,s;
int ans=0;
scanf("%d%d%d",&V,&m,&s);
for(int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
G[a].push_back(edge(b,c));
G[b].push_back(edge(a,c));
e[i].from=a,e[i].to=b,e[i].c=c;
}
scanf("%d",&l);
dijkstra(s);
for(int i=0;i<m;i++)
{
int u=e[i].from,v=e[i].to,cost=e[i].c;
if(d[u]<l && l-d[u]<cost && d[v]+cost-(l-d[u])>l) ans++;
if(d[v]<l && l-d[v]<cost && d[u]+cost-(l-d[v])>l) ans++;
if(d[u]<l && d[v]<l && d[u]+d[v]+cost==2*l) ans++;
}
for(int i=1;i<=V;i++)
if(d[i]==l) ans++;
cout<<ans<<endl;
return 0;
}