SansPapyrus683

IOI Walls

Aug 9th, 2021
1,592
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.95 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <map>
  4. #include <algorithm>
  5.  
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. using std::pair;
  10.  
  11. // https://dmoj.ca/problem/ioi00p4 (input ommitted due to length)
  12. int main() {
  13.     int region_num;
  14.     int town_num;
  15.     int member_num;
  16.     std::cin >> region_num >> town_num >> member_num;
  17.  
  18.     vector<int> members(member_num);
  19.     for (int& m : members) {
  20.         std::cin >> m;
  21.         m--;
  22.     }
  23.     vector<vector<int>> town_regions(region_num);
  24.     vector<vector<pair<int, int>>> regions(region_num);
  25.     for (int r = 0; r < region_num; r++) {
  26.         int border_num;
  27.         std::cin >> border_num;
  28.         vector<int> towns(border_num);
  29.         for (int& t : towns) {
  30.             std::cin >> t;
  31.             t--;
  32.             town_regions[t].push_back(r);
  33.         }
  34.         for (int t = 0; t < border_num; t++) {
  35.             regions[r].push_back({towns[t], towns[(t + 1) % border_num]});
  36.         }
  37.     }
  38.    
  39.     std::map<pair<int, int>, int> prev_walls;
  40.     vector<vector<int>> neighbors(region_num);
  41.     for (int r = 0; r < region_num; r++) {
  42.         for (const pair<int, int>& w : regions[r]) {
  43.             if (prev_walls.count(w)) {
  44.                 // dupes might happen but that doesn't really matter
  45.                 neighbors[r].push_back(prev_walls[w]);
  46.                 neighbors[prev_walls[w]].push_back(r);
  47.             } else {
  48.                 prev_walls[w] = r;
  49.                 pair<int, int> reverse{w.second, w.first};
  50.                 prev_walls[reverse] = r;
  51.             }
  52.         }
  53.     }
  54.  
  55.     vector<vector<int>> min_crossings(region_num, vector<int>(region_num));
  56.     for (int start = 0; start < region_num; start++) {
  57.         int moves = 0;
  58.         vector<bool> visited(region_num);
  59.         vector<int> frontier{start};
  60.         visited[start] = true;
  61.         while (!frontier.empty()) {
  62.             vector<int> in_line;
  63.             moves++;
  64.             for (int r : frontier) {
  65.                 for (int n : neighbors[r]) {
  66.                     if (!visited[n]) {
  67.                         min_crossings[start][n] = moves;
  68.                         visited[n] = true;
  69.                         in_line.push_back(n);
  70.                     }
  71.                 }
  72.             }
  73.             frontier = in_line;
  74.         }
  75.     }
  76.  
  77.     int min_crossing_sum = INT32_MAX;
  78.     int best_region = -1;
  79.     for (int meeting = 0; meeting < region_num; meeting++) {
  80.         int this_min_cross = 0;
  81.         for (int m : members) {
  82.             int m_min_crossings = INT32_MAX;
  83.             for (int t : town_regions[m]) {
  84.                 m_min_crossings = std::min(m_min_crossings, min_crossings[t][meeting]);
  85.             }
  86.             this_min_cross += m_min_crossings;
  87.         }
  88.         if (this_min_cross < min_crossing_sum) {
  89.             min_crossing_sum = this_min_cross;
  90.             best_region = meeting;
  91.         }
  92.     }
  93.     cout << min_crossing_sum << endl << best_region + 1 << endl;
  94. }
  95.  
Advertisement
Add Comment
Please, Sign In to add comment