Advertisement
Georgiy1108

Untitled

Jan 18th, 2025
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.91 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <climits>
  5. #include <cstring>
  6.  
  7. using namespace std;
  8.  
  9. const int INF = INT_MAX;
  10.  
  11. // Структура для представления ребра
  12. struct Edge {
  13.     int to, capacity, cost, flow, reverse;
  14. };
  15.  
  16. vector<vector<Edge>> graph;
  17. int N, M; // Количество чисел и регистров
  18.  
  19. // Добавление ребра в граф
  20. void addEdge(int from, int to, int capacity, int cost) {
  21.     Edge forward = {to, capacity, cost, 0, (int)graph[to].size()};
  22.     Edge backward = {from, 0, -cost, 0, (int)graph[from].size()};
  23.     graph[from].push_back(forward);
  24.     graph[to].push_back(backward);
  25. }
  26.  
  27. // Подсчет количества единичных битов (popcount)
  28. int popcount(int x) {
  29.     return __builtin_popcount(x);
  30. }
  31.  
  32. // MinCostMaxFlow с использованием Беллмана-Форда
  33. pair<int, int> minCostMaxFlow(int source, int sink, int nodes) {
  34.     int flow = 0, cost = 0;
  35.  
  36.     while (true) {
  37.         vector<int> dist(nodes, INF), parent(nodes, -1), parentEdge(nodes, -1);
  38.         vector<bool> inQueue(nodes, false);
  39.         queue<int> q;
  40.  
  41.         dist[source] = 0;
  42.         q.push(source);
  43.         inQueue[source] = true;
  44.  
  45.         while (!q.empty()) {
  46.             int u = q.front();
  47.             q.pop();
  48.             inQueue[u] = false;
  49.  
  50.             for (int i = 0; i < (int)graph[u].size(); ++i) {
  51.                 Edge &e = graph[u][i];
  52.                 if (e.flow < e.capacity && dist[u] + e.cost < dist[e.to]) {
  53.                     dist[e.to] = dist[u] + e.cost;
  54.                     parent[e.to] = u;
  55.                     parentEdge[e.to] = i;
  56.                     if (!inQueue[e.to]) {
  57.                         q.push(e.to);
  58.                         inQueue[e.to] = true;
  59.                     }
  60.                 }
  61.             }
  62.         }
  63.  
  64.         if (dist[sink] == INF) break; // Если путь до стока не найден
  65.  
  66.         // Найти минимальный остаточный поток по пути
  67.         int pushFlow = INF;
  68.         for (int u = sink; u != source; u = parent[u]) {
  69.             int prev = parent[u];
  70.             int edgeIdx = parentEdge[u];
  71.             pushFlow = min(pushFlow, graph[prev][edgeIdx].capacity - graph[prev][edgeIdx].flow);
  72.         }
  73.  
  74.         // Пропустить поток и обновить ребра
  75.         for (int u = sink; u != source; u = parent[u]) {
  76.             int prev = parent[u];
  77.             int edgeIdx = parentEdge[u];
  78.             graph[prev][edgeIdx].flow += pushFlow;
  79.             graph[u][graph[prev][edgeIdx].reverse].flow -= pushFlow;
  80.             cost += pushFlow * graph[prev][edgeIdx].cost;
  81.         }
  82.  
  83.         flow += pushFlow;
  84.     }
  85.  
  86.     return {flow, cost};
  87. }
  88.  
  89. int main() {
  90.     cin >> N >> M;
  91.     vector<int> sequence(N);
  92.     for (int i = 0; i < N; ++i) {
  93.         cin >> sequence[i];
  94.     }
  95.  
  96.     int source = 0;
  97.     int sink = N + N + M + 1; // Источник + write[i] + print[i] + регистры + сток
  98.     graph.resize(sink + 1);
  99.  
  100.     // Добавляем вершины для записи чисел
  101.     for (int i = 0; i < N; ++i) {
  102.         addEdge(source, i + 1, 1, popcount(sequence[i]));  // S -> write[i]
  103.         addEdge(i + 1, N + i + 1, 1, 0);                   // write[i] -> print[i]
  104.         addEdge(N + i + 1, sink, 1, 0);                    // print[i] -> T
  105.     }
  106.  
  107.     // Добавляем регистры
  108.     for (int j = 0; j < M; ++j) {
  109.         for (int i = 0; i < N; ++i) {
  110.             addEdge(i + 1, 2 * N + j + 1, 1, 0);           // write[i] -> reg[j]
  111.             addEdge(2 * N + j + 1, N + i + 1, 1, 0);       // reg[j] -> print[i]
  112.         }
  113.     }
  114.  
  115.     // Выполняем MinCostMaxFlow
  116.     auto result = minCostMaxFlow(source, sink, sink + 1);
  117.     cout << "Минимальная стоимость: " << result.second << endl;
  118.  
  119.     return 0;
  120. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement