제출 #1320300

#제출 시각아이디문제언어결과실행 시간메모리
1320300ro9669통행료 (APIO13_toll)C++20
100 / 100
1685 ms7208 KiB
#include <iostream> #include <vector> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const int MAXN = 100005; const int MAXM = 300005; const int MAXK = 25; struct Edge { int u, v, w; }; bool compareEdges(const Edge& a, const Edge& b) { return a.w < b.w; } int N, M, K; Edge old_edges[MAXM]; pair<int, int> new_roads[MAXK]; int p_count[MAXN]; struct DSU { int parent[MAXN]; void init(int n) { for (int i = 0; i <= n; i++) parent[i] = i; } int find(int i) { if (parent[i] == i) return i; return parent[i] = find(parent[i]); } bool unite(int i, int j) { int root_i = find(i), root_j = find(j); if (root_i != root_j) { parent[root_i] = root_j; return true; } return false; } } dsu, dsu_super; int super_node[MAXN], mapping[MAXN], v_cnt; ll super_people[MAXK * 2]; vector<Edge> reduced_old; struct GraphEdge { int to, weight, id; }; vector<GraphEdge> adj[MAXK * 2]; ll subtree_people[MAXK * 2]; int edge_fees[MAXK]; // Tính tổng dân số trong cây con của đồ thị nén void get_subtree_people(int u, int p) { subtree_people[u] = super_people[u]; for (size_t i = 0; i < adj[u].size(); ++i) { if (adj[u][i].to == p) continue; get_subtree_people(adj[u][i].to, u); subtree_people[u] += subtree_people[adj[u][i].to]; } } // Tìm đường đi và cập nhật phí cầu đường tối đa cho cạnh của Mr Greedy bool update_path(int u, int target, int p, int w_limit) { if (u == target) return true; for (size_t i = 0; i < adj[u].size(); ++i) { if (adj[u][i].to == p) continue; if (update_path(adj[u][i].to, target, u, w_limit)) { if (adj[u][i].id >= 0) edge_fees[adj[u][i].id] = min(edge_fees[adj[u][i].id], w_limit); return true; } } return false; } // Tính tổng doanh thu cho mask hiện tại ll calculate_revenue(int u, int p) { ll res = 0; for (size_t i = 0; i < adj[u].size(); ++i) { if (adj[u][i].to == p) continue; if (adj[u][i].id >= 0) res += (ll)subtree_people[adj[u][i].to] * edge_fees[adj[u][i].id]; res += calculate_revenue(adj[u][i].to, u); } return res; } int main() { ios::sync_with_stdio(false); cin.tie(0); if (!(cin >> N >> M >> K)) return 0; for (int i = 0; i < M; i++) cin >> old_edges[i].u >> old_edges[i].v >> old_edges[i].w; sort(old_edges, old_edges + M, compareEdges); for (int i = 0; i < K; i++) cin >> new_roads[i].first >> new_roads[i].second; for (int i = 1; i <= N; i++) cin >> p_count[i]; // Tìm MST cơ bản dsu.init(N); vector<Edge> mst_all; for (int i = 0; i < M; i++) if (dsu.unite(old_edges[i].u, old_edges[i].v)) mst_all.push_back(old_edges[i]); // Xác định các siêu đỉnh (nén đồ thị) dsu.init(N); for (int i = 0; i < K; i++) dsu.unite(new_roads[i].first, new_roads[i].second); dsu_super.init(N); for (size_t i = 0; i < mst_all.size(); ++i) { if (dsu.unite(mst_all[i].u, mst_all[i].v)) dsu_super.unite(mst_all[i].u, mst_all[i].v); else reduced_old.push_back(mst_all[i]); } memset(mapping, -1, sizeof(mapping)); v_cnt = 0; for (int i = 1; i <= N; i++) { int r = dsu_super.find(i); if (mapping[r] == -1) mapping[r] = v_cnt++; super_node[i] = mapping[r]; super_people[super_node[i]] += p_count[i]; } ll max_rev = 0; // Duyệt tất cả các tập con cạnh mới (2^K) for (int mask = 1; mask < (1 << K); mask++) { dsu.init(v_cnt); bool cycle = false; for (int i = 0; i < v_cnt; i++) adj[i].clear(); for (int i = 0; i < K; i++) if ((mask >> i) & 1) { int u = super_node[new_roads[i].first], v = super_node[new_roads[i].second]; if (!dsu.unite(u, v)) { cycle = true; break; } adj[u].push_back({v, 0, i}); adj[v].push_back({u, 0, i}); } if (cycle) continue; vector<Edge> unused; for (size_t i = 0; i < reduced_old.size(); ++i) { int u = super_node[reduced_old[i].u], v = super_node[reduced_old[i].v]; if (dsu.unite(u, v)) { adj[u].push_back({v, reduced_old[i].w, -1}); adj[v].push_back({u, reduced_old[i].w, -1}); } else unused.push_back(reduced_old[i]); } for (int i = 0; i < K; i++) edge_fees[i] = 1000001; // Max fee ban đầu for (size_t i = 0; i < unused.size(); ++i) { update_path(super_node[unused[i].u], super_node[unused[i].v], -1, unused[i].w); } get_subtree_people(super_node[1], -1); max_rev = max(max_rev, calculate_revenue(super_node[1], -1)); } cout << max_rev << endl; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...