#include <iostream>
#include <vector>
#include <queue>
#include <limits>
// Dùng hằng số để code dễ đọc và bảo trì hơn
constexpr int MAXN = 100001;
// Định nghĩa giá trị vô cực cho kiểu long long
constexpr long long INF = std::numeric_limits<long long>::max();
typedef long long ll;
using namespace std;
// === Biến toàn cục ===
int N, M; // Số đỉnh và số cạnh
int S, T, U, V; // Các đỉnh đặc biệt
// Danh sách kề: graph[i] chứa các cặp {đỉnh kề, trọng số}
vector<pair<ll, ll>> graph[MAXN];
// Mảng lưu khoảng cách:
// du[i]: khoảng cách ngắn nhất từ U đến i
// dv[i]: khoảng cách ngắn nhất từ V đến i
vector<ll> du(MAXN);
vector<ll> dv(MAXN);
// Biến lưu kết quả cuối cùng
ll ans;
// === Hàm Dijkstra chuẩn ===
// Tìm đường đi ngắn nhất từ một đỉnh `start` đến tất cả các đỉnh khác.
// Kết quả được lưu vào mảng `dist`.
void dijkstra(int start, vector<ll>& dist) {
// 1. Khởi tạo
// Điền tất cả khoảng cách là vô cực
dist.assign(N + 1, INF);
// Khoảng cách từ đỉnh bắt đầu đến chính nó là 0
dist[start] = 0;
// Priority queue (min-heap) lưu các cặp {khoảng cách, đỉnh}
// Dùng `greater` để biến nó thành min-heap
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> pq;
pq.push({0, start});
// 2. Vòng lặp chính của Dijkstra
while (!pq.empty()) {
// Lấy đỉnh có khoảng cách nhỏ nhất ra khỏi hàng đợi
ll d = pq.top().first;
int u = pq.top().second;
pq.pop();
// Tối ưu hóa: Nếu khoảng cách đã lưu cũ hơn, bỏ qua
if (d > dist[u]) {
continue;
}
// 3. Duyệt các đỉnh kề (relax edges)
for (auto& edge : graph[u]) {
int v_neighbor = edge.first;
ll weight = edge.second;
// Nếu tìm thấy đường đi tốt hơn đến v_neighbor
if (dist[u] + weight < dist[v_neighbor]) {
dist[v_neighbor] = dist[u] + weight;
pq.push({dist[v_neighbor], v_neighbor});
}
}
}
}
// === Hàm Dijkstra sửa đổi để giải quyết bài toán ===
// Tìm đường đi ngắn nhất từ `start` đến `end`, đồng thời tối ưu hóa một tiêu chí phụ.
// Tiêu chí phụ: Tìm đường đi ngắn nhất có tổng (min(du) + min(dv)) trên đường đi là nhỏ nhất.
void solve_path(int start, int end) {
// Mảng lưu đường đi ngắn nhất từ `start`
vector<ll> dist_from_start(N + 1, INF);
// dp[0][i]: giá trị du[] nhỏ nhất trên đường đi ngắn nhất từ `start` đến `i`
vector<ll> min_du_on_path(N + 1, INF);
// dp[1][i]: giá trị dv[] nhỏ nhất trên đường đi ngắn nhất từ `start` đến `i`
vector<ll> min_dv_on_path(N + 1, INF);
dist_from_start[start] = 0;
min_du_on_path[start] = du[start];
min_dv_on_path[start] = dv[start];
// Priority queue lưu {khoảng cách, đỉnh}
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> pq;
pq.push({0, start});
while (!pq.empty()) {
ll d = pq.top().first;
int u = pq.top().second;
pq.pop();
if (d > dist_from_start[u]) {
continue;
}
for (auto& edge : graph[u]) {
int v_neighbor = edge.first;
ll weight = edge.second;
ll new_dist = dist_from_start[u] + weight;
// Tính giá trị min_du và min_dv mới nếu đi qua cạnh (u, v_neighbor)
ll new_min_du = min(min_du_on_path[u], du[v_neighbor]);
ll new_min_dv = min(min_dv_on_path[u], dv[v_neighbor]);
// Trường hợp 1: Tìm thấy một đường đi NGẮN HƠN đến v_neighbor
if (new_dist < dist_from_start[v_neighbor]) {
dist_from_start[v_neighbor] = new_dist;
min_du_on_path[v_neighbor] = new_min_du;
min_dv_on_path[v_neighbor] = new_min_dv;
pq.push({new_dist, v_neighbor});
}
// Trường hợp 2: Tìm thấy một đường đi khác CÓ CÙNG ĐỘ DÀI ngắn nhất
else if (new_dist == dist_from_start[v_neighbor]) {
// Ta kiểm tra xem đường đi mới này có tốt hơn về tiêu chí phụ không
if (new_min_du + new_min_dv < min_du_on_path[v_neighbor] + min_dv_on_path[v_neighbor]) {
min_du_on_path[v_neighbor] = new_min_du;
min_dv_on_path[v_neighbor] = new_min_dv;
// Đẩy lại vào PQ để xét các đường đi tiếp theo từ đỉnh này
// với giá trị tiêu chí phụ đã được cải thiện.
pq.push({new_dist, v_neighbor});
}
}
}
}
// Sau khi thuật toán kết thúc, nếu có đường đi đến `end`
if (dist_from_start[end] != INF) {
// Cập nhật kết quả toàn cục
ans = min(ans, min_du_on_path[end] + min_dv_on_path[end]);
}
}
int main() {
// Tăng tốc độ nhập xuất
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> N >> M >> S >> T >> U >> V;
for (int i = 0; i < M; i++) {
int a, b, c;
cin >> a >> b >> c;
graph[a].push_back({b, c});
graph[b].push_back({a, c});
}
// 1. Chạy Dijkstra thông thường từ U và V để tính trước khoảng cách
// du[i] và dv[i] cho mọi đỉnh i.
dijkstra(U, du);
dijkstra(V, dv);
// 2. Khởi tạo kết quả ban đầu. Một trường hợp có thể xảy ra là
// đường đi tối ưu không cần đi qua S và T, mà chỉ cần nối U và V.
ans = du[V];
// 3. Chạy thuật toán Dijkstra sửa đổi để tìm đường đi từ S->T và T->S
// và cập nhật kết quả.
solve_path(S, T);
solve_path(T, S);
cout << ans << '\n';
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... |