|
| 1 | +#include <cstdio> |
| 2 | +#include <cstring> |
| 3 | +#include <algorithm> |
| 4 | +#include <utility> |
| 5 | +#include <vector> |
| 6 | +#include <map> |
| 7 | +#include <queue> |
| 8 | + |
| 9 | +using namespace std; |
| 10 | + |
| 11 | +const int MAXN = 100005; |
| 12 | +int n, m, start; |
| 13 | +long long l; |
| 14 | + |
| 15 | +vector<pair<int, long long> > graph[MAXN]; |
| 16 | +long long dist[MAXN]; |
| 17 | + |
| 18 | +typedef pair<long long, int> state; |
| 19 | + |
| 20 | +void dijkstra() { |
| 21 | + // find the shortest path from the source to all nodes |
| 22 | + |
| 23 | + memset(dist, -1, sizeof(dist)); |
| 24 | + priority_queue<state, vector<state>, greater<state> > pq; |
| 25 | + pq.push(make_pair(0LL, start)); |
| 26 | + |
| 27 | + while (!pq.empty()) { |
| 28 | + state cur = pq.top(); |
| 29 | + pq.pop(); |
| 30 | + |
| 31 | + long long dist_here = cur.first; |
| 32 | + int pos = cur.second; |
| 33 | + |
| 34 | + if (dist[pos] != -1 and dist[pos] <= dist_here) |
| 35 | + continue; |
| 36 | + |
| 37 | + dist[pos] = dist_here; |
| 38 | + |
| 39 | + for (pair<int, long long> edge : graph[pos]) { |
| 40 | + int next_place = edge.first; |
| 41 | + long long next_dist = dist_here + edge.second; |
| 42 | + |
| 43 | + if (dist[next_place] == -1 or dist_here < dist[next_place]) { |
| 44 | + pq.push(make_pair(next_dist, next_place)); |
| 45 | + } |
| 46 | + } |
| 47 | + } |
| 48 | +} |
| 49 | + |
| 50 | +int main() { |
| 51 | + scanf("%d %d %d", &n, &m, &start); |
| 52 | + |
| 53 | + int u, v; |
| 54 | + long long w; |
| 55 | + for (int i = 0; i < m; ++i) { |
| 56 | + scanf("%d %d %lld", &u, &v, &w); |
| 57 | + graph[u].push_back(make_pair(v, w)); |
| 58 | + graph[v].push_back(make_pair(u, w)); |
| 59 | + } |
| 60 | + |
| 61 | + scanf("%lld", &l); |
| 62 | + |
| 63 | + dijkstra(); |
| 64 | + |
| 65 | + long long ans = 0; |
| 66 | + for (u = 1; u <= n; ++u) { |
| 67 | + // printf("City %d at dist %lld\n", u, dist[u]); |
| 68 | + if (dist[u] == l) { |
| 69 | + // printf("Silo at city %d\n", u); |
| 70 | + ++ans; |
| 71 | + continue; |
| 72 | + } |
| 73 | + |
| 74 | + if (dist[u] > l) { |
| 75 | + continue; |
| 76 | + } |
| 77 | + |
| 78 | + for (pair<int, long long> edge : graph[u]) { |
| 79 | + v = edge.first; |
| 80 | + w = edge.second; |
| 81 | + |
| 82 | + if (dist[u] + w <= l) { |
| 83 | + continue; |
| 84 | + } |
| 85 | + |
| 86 | + // edge case: the distance is the same from either side |
| 87 | + if (u < v and |
| 88 | + dist[u] < l and l < dist[u] + w and |
| 89 | + dist[v] < l and l < dist[v] + w and |
| 90 | + dist[u] + dist[v] + w == 2 * l) { |
| 91 | + // printf("Midpoint silo between %d and %d\n", u, v); |
| 92 | + ++ans; |
| 93 | + } |
| 94 | + |
| 95 | + // consider the point coming from u |
| 96 | + if (dist[u] < l and l < dist[u] + w) { |
| 97 | + // the point is l - dist[u] away from u |
| 98 | + long long u_dist = l - dist[u]; |
| 99 | + // the point is dist[v] + w - u_dist away from v |
| 100 | + if (l < dist[v] + w - u_dist) { |
| 101 | + // printf("Silo at distance %lld along edge between %d and %d\n", u_dist, u, v); |
| 102 | + ++ans; |
| 103 | + } |
| 104 | + } |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + printf("%lld\n", ans); |
| 109 | + |
| 110 | + return 0; |
| 111 | +} |
0 commit comments