Submission #1269638

#TimeUsernameProblemLanguageResultExecution timeMemory
1269638bnd2100Robot (JOI21_ho_t4)C++20
0 / 100
3093 ms5136 KiB
#include <iostream> #include <vector> #include <queue> #include <map> #include <algorithm> using namespace std; const long long INF = 1e18; // Sử dụng giá trị lớn cho vô cùng struct Road { int u, v, id; // id là chỉ số của con đường trong mảng roads_data int initial_color; int cost_to_change; }; struct State { long long cost; int node; bool operator>(const State& other) const { return cost > other.cost; } }; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int N, M; cin >> N >> M; vector<Road> roads_data(M); // adj[node] lưu danh sách các cặp {neighbor_node, road_id} vector<vector<pair<int, int>>> adj(N + 1); for (int i = 0; i < M; ++i) { int u, v, c, p; cin >> u >> v >> c >> p; roads_data[i] = {u, v, i, c, p}; adj[u].push_back({v, i}); adj[v].push_back({u, i}); // Đường đi hai chiều } vector<long long> dist(N + 1, INF); priority_queue<State, vector<State>, greater<State>> pq; dist[1] = 0; pq.push({0, 1}); while (!pq.empty()) { State current = pq.top(); pq.pop(); long long current_cost = current.cost; int u = current.node; if (current_cost > dist[u]) { continue; } // Duyệt qua tất cả các màu có thể (1 đến M) // Giả sử chúng ta muốn nói màu 'target_color' từ node 'u' for (int target_color = 1; target_color <= M; ++target_color) { long long cost_to_make_move = 0; int potential_next_node = -1; // Node mà chúng ta sẽ đến nếu nói target_color bool possible_move = true; // Có thể thực hiện nước đi này không // Liệt kê tất cả các con đường xuất phát từ 'u' vector<int> roads_from_u_indices; for (auto& edge : adj[u]) { roads_from_u_indices.push_back(edge.second); } // Bước 1: Tìm con đường tiềm năng duy nhất để đi // Nếu có nhiều đường màu target_color, hoặc đường đó không dẫn đến một node duy nhất, // thì chúng ta phải thay đổi màu của các đường thừa. // Cách tính chi phí cho mỗi màu 'target_color' từ 'u': // Chúng ta muốn có duy nhất một con đường 'X' xuất phát từ 'u' có màu 'target_color', // và các con đường khác đều không có màu 'target_color'. vector<pair<int, int>> roads_with_target_color_from_u; // {road_idx, neighbor_node} for (int road_idx : roads_from_u_indices) { Road& r = roads_data[road_idx]; int neighbor_node = (r.u == u) ? r.v : r.u; if (r.initial_color == target_color) { roads_with_target_color_from_u.push_back({road_idx, neighbor_node}); } } // Trường hợp 1: Không có con đường nào ban đầu có màu target_color // Chúng ta phải chọn một con đường và thay đổi màu của nó. // Để tối ưu, chúng ta sẽ chọn con đường có chi phí thay đổi thấp nhất. if (roads_with_target_color_from_u.empty()) { long long min_change_cost_to_create_path = INF; int best_road_idx_to_change = -1; for (int road_idx : roads_from_u_indices) { Road& r = roads_data[road_idx]; if (r.cost_to_change < min_change_cost_to_create_path) { min_change_cost_to_create_path = r.cost_to_change; best_road_idx_to_change = road_idx; } } if (best_road_idx_to_change != -1) { cost_to_make_move += min_change_cost_to_create_path; Road& best_r = roads_data[best_road_idx_to_change]; potential_next_node = (best_r.u == u) ? best_r.v : best_r.u; } else { possible_move = false; // Không có đường nào để thay đổi màu } } // Trường hợp 2: Có một hoặc nhiều con đường ban đầu có màu target_color else { // Nếu có 1 con đường ban đầu có màu target_color if (roads_with_target_color_from_u.size() == 1) { potential_next_node = roads_with_target_color_from_u[0].second; // Không cần thay đổi màu của nó, chi phí là 0 cho đường này } // Nếu có nhiều hơn 1 con đường ban đầu có màu target_color else { // Tìm con đường có chi phí thay đổi thấp nhất để giữ lại làm màu target_color, // và thay đổi màu của các con đường còn lại. long long min_cost_to_keep_one = INF; int best_road_to_keep_idx = -1; int best_road_to_keep_neighbor = -1; for (auto& p : roads_with_target_color_from_u) { int road_idx = p.first; int neighbor = p.second; Road& r = roads_data[road_idx]; long long current_temp_cost = 0; for (auto& other_p : roads_with_target_color_from_u) { int other_road_idx = other_p.first; if (other_road_idx != road_idx) { current_temp_cost += roads_data[other_road_idx].cost_to_change; } } if (current_temp_cost < min_cost_to_keep_one) { min_cost_to_keep_one = current_temp_cost; best_road_to_keep_idx = road_idx; best_road_to_keep_neighbor = neighbor; } } cost_to_make_move += min_cost_to_keep_one; potential_next_node = best_road_to_keep_neighbor; } } // Nếu có một nước đi hợp lệ với chi phí đã tính if (possible_move && potential_next_node != -1) { if (current_cost + cost_to_make_move < dist[potential_next_node]) { dist[potential_next_node] = current_cost + cost_to_make_move; pq.push({dist[potential_next_node], potential_next_node}); } } } } if (dist[N] == INF) { cout << -1 << endl; } else { cout << dist[N] << endl; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...