Guest User

Kuhn_AC

a guest
Jan 29th, 2023
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.29 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. class Matching {
  5. public:
  6. int left_;
  7. int right_;
  8. int pairs_;
  9. vector <int> used_;
  10. vector <int> match_left_;
  11. vector <int> match_right_;
  12. vector <vector <int>> adj_;
  13.  
  14. explicit Matching(int n, int m)
  15. : left_(n),
  16. right_(m),
  17. adj_(n),
  18. used_(n),
  19. pairs_(0),
  20. match_left_(n, -1),
  21. match_right_(m, -1) {
  22. }
  23.  
  24. [[gnu::always_inline]]
  25. inline void AddEdge(int left, int right) {
  26. adj_[left].emplace_back(right);
  27. }
  28.  
  29. bool Dfs(int node) {
  30. if (used_[node] == pairs_ + 1) {
  31. return false;
  32. }
  33. used_[node] = pairs_ + 1;
  34. for (const int& to : adj_[node]) {
  35. if (match_right_[to] == -1) {
  36. match_left_[node] = to;
  37. match_right_[to] = node;
  38. return true;
  39. }
  40. }
  41.  
  42. for (const int& to : adj_[node]) {
  43. if (Dfs(match_right_[to])) {
  44. match_left_[node] = to;
  45. match_right_[to] = node;
  46. return true;
  47. }
  48. }
  49.  
  50. return false;
  51. }
  52.  
  53. template <bool Shuffle = false>
  54. vector <pair <int, int>> Solve() {
  55. vector <int> order(left_);
  56. iota(order.begin(), order.end(), 0);
  57.  
  58. if constexpr (Shuffle) {
  59. shuffle(order.begin(), order.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));
  60. for (vector <int>& adj_list : adj_) {
  61. shuffle(adj_list.begin(), adj_list.end(), mt19937(chrono::steady_clock::now().time_since_epoch().count()));
  62. }
  63. }
  64.  
  65. for (const int& node : order) {
  66. pairs_ += Dfs(node);
  67. }
  68.  
  69. vector <pair <int, int>> result;
  70. result.reserve(pairs_);
  71. for (int i = 0; i < left_; ++i) {
  72. if (match_left_[i] != -1) {
  73. result.emplace_back(i, match_left_[i]);
  74. }
  75. }
  76.  
  77. return result;
  78. }
  79. };
  80.  
  81. void RunCase() {
  82. int n, m, a, b;
  83. cin >> n >> m >> a >> b;
  84.  
  85. vector <vector <char>> grid(n, vector <char>(m));
  86. for (auto& row : grid) {
  87. for (auto& c : row) {
  88. cin >> c;
  89. }
  90. }
  91.  
  92. int vacant = 0;
  93. for (const auto& row : grid) {
  94. for (const auto& c : row) {
  95. vacant += (c == '*');
  96. }
  97. }
  98.  
  99. if (vacant == 0) {
  100. cout << "0\n";
  101. return;
  102. }
  103.  
  104. if (2 * b <= a) {
  105. cout << vacant * b * 2 << "\n";
  106. return;
  107. }
  108.  
  109. const int grid_size = n * m;
  110. Matching matching(grid_size / 2 + grid_size % 2, grid_size / 2);
  111.  
  112. constexpr int dx[] = {-1, 0, 0, 1};
  113. constexpr int dy[] = {0, -1, 1, 0};
  114.  
  115. vector <int> code(n * m);
  116. for (int i = 2; i < n * m; ++i) {
  117. code[i] = code[i - 2] + 1;
  118. }
  119.  
  120. for (int i = 0; i < n; ++i) {
  121. for (int j = i % 2; j < m; j += 2) {
  122. if (grid[i][j] == '.') {
  123. continue;
  124. }
  125.  
  126. for (size_t k = 0; k < 4; ++k) {
  127. int new_i = i + dx[k];
  128. int new_j = j + dy[k];
  129. if (0 <= new_i && new_i <= n - 1
  130. && 0 <= new_j && new_j <= m - 1
  131. && grid[new_i][new_j] != '.') {
  132. matching.AddEdge(code[i * m + j], code[new_i * m + new_j]);
  133. }
  134. }
  135. }
  136. }
  137.  
  138. int mat = matching.Solve().size();
  139. assert(mat * 2 <= vacant);
  140. cout << mat * a + b * (vacant - 2 * mat) << "\n";
  141. }
  142.  
  143. int main() {
  144. std::ios_base::sync_with_stdio(false);
  145. std::cin.tie(nullptr);
  146. int tt = 1;
  147. //std::cin >> tt;
  148. while (tt--) {
  149. RunCase();
  150. }
  151. return 0;
  152. }
Advertisement
Add Comment
Please, Sign In to add comment