题目大意:
给出一个图,一个源点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; }
时间: 2024-10-03 09:30:45