結果
問題 |
No.1615 Double Down
|
ユーザー |
![]() |
提出日時 | 2025-05-14 13:20:26 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 6,199 bytes |
コンパイル時間 | 1,546 ms |
コンパイル使用メモリ | 103,604 KB |
実行使用メモリ | 25,712 KB |
最終ジャッジ日時 | 2025-05-14 13:22:25 |
合計ジャッジ時間 | 24,305 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | -- * 3 |
other | TLE * 1 -- * 53 |
ソースコード
#include <iostream> #include <vector> #include <map> #include <algorithm> #include <queue> // Use long long for costs and total sum as prices can be large (2^30) // and sum of prices can exceed 32-bit integer limit. const long long INF = 1e18; // A large enough value for infinity struct Edge { int to; // Destination vertex int capacity; // Capacity of the edge int flow; // Current flow through the edge long long cost; // Cost per unit of flow int rev; // Index of the reverse edge in adj[to] }; std::vector<std::vector<Edge>> adj; // Adjacency list for the graph std::vector<long long> dist; // Shortest distance from source in SPFA std::vector<int> parent_v; // Parent vertex in shortest path std::vector<int> parent_e; // Parent edge index in shortest path int V_flow; // Total number of vertices in the flow network // Adds an edge and its residual edge void add_edge(int u, int v, int cap, long long cost) { adj[u].push_back({v, cap, 0, cost, (int)adj[v].size()}); adj[v].push_back({u, 0, 0, -cost, (int)adj[u].size() - 1}); // Residual edge for 0 cap initially } // Min-cost max-flow algorithm using SPFA // Finds paths and augments flow as long as it reduces total cost (increases profit) // total_flow_val will store the number of matched pairs. long long min_cost_max_flow_calc(int s, int t, int& total_flow_val) { long long total_cost = 0; total_flow_val = 0; dist.resize(V_flow); parent_v.resize(V_flow); parent_e.resize(V_flow); while (true) { std::fill(dist.begin(), dist.end(), INF); dist[s] = 0; std::vector<bool> in_queue(V_flow, false); std::queue<int> q; q.push(s); in_queue[s] = true; // SPFA to find shortest path in terms of cost while (!q.empty()) { int u = q.front(); q.pop(); in_queue[u] = false; for (int i = 0; i < adj[u].size(); ++i) { Edge& e = adj[u][i]; if (e.capacity - e.flow > 0 && dist[e.to] > dist[u] + e.cost) { dist[e.to] = dist[u] + e.cost; parent_v[e.to] = u; parent_e[e.to] = i; if (!in_queue[e.to]) { q.push(e.to); in_queue[e.to] = true; } } } } // If no path found, or path found has non-negative cost (no more profit) if (dist[t] == INF || dist[t] >= 0) { // dist[t] >= 0 means we can't add more items to increase profit // (as costs are -price, so positive cost means negative profit) break; } // All edge capacities for matching are 1. So path_flow is 1. int path_flow = 1; total_flow_val += path_flow; // One more item matched total_cost += (long long)path_flow * dist[t]; // Add cost of this path to total // Augment flow along the path int cur = t; while (cur != s) { int prev = parent_v[cur]; int edge_idx = parent_e[cur]; adj[prev][edge_idx].flow += path_flow; adj[cur][adj[prev][edge_idx].rev].flow -= path_flow; // Update flow on reverse edge cur = prev; } } return total_cost; } struct BidInfo { int x_orig, y_orig, z; // Original buyer ID, item ID, and Z value long long price; // Calculated price 2^Z }; int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); int N_max, M_max, K_val, L_bids; // Max IDs N, M, max power K, num_bids L std::cin >> N_max >> M_max >> K_val >> L_bids; std::vector<BidInfo> bids(L_bids); std::map<int, int> buyer_orig_to_idx; // Map original buyer ID to 0-indexed internal ID std::map<int, int> item_orig_to_idx; // Map original item ID to 0-indexed internal ID int next_buyer_idx = 0; int next_item_idx = 0; for (int i = 0; i < L_bids; ++i) { std::cin >> bids[i].x_orig >> bids[i].y_orig >> bids[i].z; bids[i].price = (1LL << bids[i].z); // Price is 2^Z // Assign new compact index if this buyer/item ID is seen for the first time if (buyer_orig_to_idx.find(bids[i].x_orig) == buyer_orig_to_idx.end()) { buyer_orig_to_idx[bids[i].x_orig] = next_buyer_idx++; } if (item_orig_to_idx.find(bids[i].y_orig) == item_orig_to_idx.end()) { item_orig_to_idx[bids[i].y_orig] = next_item_idx++; } } int num_actual_buyers = next_buyer_idx; int num_actual_items = next_item_idx; // Define source and sink nodes for the flow network // Buyers: 0 to num_actual_buyers-1 // Items: num_actual_buyers to num_actual_buyers + num_actual_items - 1 int s_node = num_actual_buyers + num_actual_items; // Source node index int t_node = num_actual_buyers + num_actual_items + 1; // Sink node index V_flow = num_actual_buyers + num_actual_items + 2; // Total vertices in flow network adj.assign(V_flow, std::vector<Edge>()); // Initialize adjacency list // Edges from source to buyers for (int i = 0; i < num_actual_buyers; ++i) { add_edge(s_node, i, 1, 0); // cap 1, cost 0 } // Edges from items to sink for (int i = 0; i < num_actual_items; ++i) { // Item node index is i (0 to num_actual_items-1) + num_actual_buyers add_edge(num_actual_buyers + i, t_node, 1, 0); // cap 1, cost 0 } // Edges from buyers to items for each bid for (const auto& bid : bids) { int u_compact_idx = buyer_orig_to_idx[bid.x_orig]; int v_compact_idx = item_orig_to_idx[bid.y_orig] + num_actual_buyers; // Offset item indices add_edge(u_compact_idx, v_compact_idx, 1, -bid.price); // cap 1, cost -price } int total_flow = 0; // Will store total number of items sold long long min_total_cost = min_cost_max_flow_calc(s_node, t_node, total_flow); // Max revenue is -min_total_cost (because costs were negative prices) std::cout << -min_total_cost << std::endl; return 0; }