#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
// Use long long for distances to prevent overflow
typedef long long ll;
typedef std::pair<ll, ll> pll; // {distance, node}
const ll MAXN = 1e17; // A sufficiently large value for infinity
// Function to run Dijkstra from a source node
std::vector<ll> dijkstra(ll n, const std::vector<std::vector<pll>>& adj, ll source) {
std::vector<ll> dist(n, MAXN);
std::priority_queue<pll, std::vector<pll>, std::greater<pll>> pq;
dist[source] = 0;
pq.push({0, source});
while (!pq.empty()) {
pll current = pq.top();
pq.pop();
ll d = current.first;
ll u = current.second;
if (d > dist[u]) {
continue; // Already found a shorter path
}
for (const pll& edge : adj[u]) {
ll v = edge.first;
ll weight = edge.second;
if (dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
pq.push({dist[v], v});
}
}
}
return dist;
}
void solve() {
ll n, m;
std::cin >> n >> m;
n++; // Nodes are 1-indexed, so adjust size
ll s_start, t_end;
std::cin >> s_start >> t_end;
ll u_query, v_query;
std::cin >> u_query >> v_query;
std::vector<std::vector<pll>> adj(n);
std::vector<std::vector<pll>> rev_adj(n); // For Dijkstra from t_end (or finding dist_t)
for (ll i = 0; i < m; ++i) {
ll a, b, c;
std::cin >> a >> b >> c;
adj[a].push_back({b, c});
adj[b].push_back({a, c});
rev_adj[b].push_back({a, c}); // Build reverse graph for dist from t_end
rev_adj[a].push_back({b, c});
}
// Run Dijkstra from s_start to get shortest path distances
std::vector<ll> dist_s = dijkstra(n, adj, s_start);
// Run Dijkstra from t_end on the original graph to get distances from t_end
// (This is equivalent to running Dijkstra from t_end on the reverse graph)
std::vector<ll> dist_t = dijkstra(n, adj, t_end);
// Now, run Dijkstra from u_query to v_query
// The "special" edges are those on a shortest path from s_start to t_end.
// An edge (x, y) with weight w is on a shortest path from s_start to t_end
// if dist_s[x] + w + dist_t[y] == dist_s[t_end] (or dist_s[y] + w + dist_t[x] == dist_s[t_end])
// The problem implies we add edges in both directions for shortest paths.
std::vector<ll> final_dist(n, MAXN);
std::priority_queue<pll, std::vector<pll>, std::greater<pll>> pq_final;
final_dist[u_query] = 0;
pq_final.push({0, u_query});
ll min_path_length = MAXN;
while (!pq_final.empty()) {
pll current = pq_final.top();
pq_final.pop();
ll d = current.first;
ll u = current.second;
if (d > final_dist[u]) {
continue;
}
// Check if we reached the target node
if (u == v_query) {
min_path_length = std::min(min_path_length, final_dist[u]);
continue; // Can potentially stop early if looking for just one shortest path
}
// Iterate over all neighbors
for (const pll& edge : adj[u]) {
ll v = edge.first;
ll weight = edge.second;
// Option 1: Traverse original edge
ll alt1 = final_dist[u] + weight;
if (alt1 < final_dist[v]) {
final_dist[v] = alt1;
pq_final.push({alt1, v});
}
// Option 2: Traverse 'special' edges (part of s-t shortest path)
// This is where the core logic of the problem comes in.
// If the original edge (u, v) with weight 'weight' is part of an s-t shortest path.
// We consider adding this edge with 0 cost in both directions.
// This means if (u,v) is part of a shortest path from s to t,
// we can go u->v (cost 0) or v->u (cost 0).
// A more accurate interpretation for "less memory code" would be
// to only add these edges on the fly if they are beneficial.
// If (u,v) is on a shortest path from s_start to t_end
if (dist_s[u] != MAXN && dist_t[v] != MAXN && dist_s[u] + weight + dist_t[v] == dist_s[t_end]) {
// This edge (u,v) is on a shortest path. Consider 0 cost.
ll alt_special_fwd = final_dist[u] + 0; // Forward on special path
if (alt_special_fwd < final_dist[v]) {
final_dist[v] = alt_special_fwd;
pq_final.push({alt_special_fwd, v});
}
}
// If (v,u) is on a shortest path from s_start to t_end (i.e., u is 'prev' of v on SP)
// This covers the reverse direction without needing a reverse graph specifically for this check.
if (dist_s[v] != MAXN && dist_t[u] != MAXN && dist_s[v] + weight + dist_t[u] == dist_s[t_end]) {
// This edge (v,u) is on a shortest path. Consider 0 cost.
ll alt_special_bwd = final_dist[u] + 0; // Backward on special path
if (alt_special_bwd < final_dist[v]) {
final_dist[v] = alt_special_bwd;
pq_final.push({alt_special_bwd, v});
}
}
}
}
std::cout << final_dist[v_query] << "\n";
}
int main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
solve();
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |