Advertisement
Guest User

1213.cpp

a guest
Aug 23rd, 2018
1,411
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.19 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <vector>
  3. #include <functional>
  4. #include <algorithm>
  5. #include <cassert>
  6.  
  7. int main() {
  8.     // freopen("input.txt", "rt", stdin);
  9.     // freopen("output.txt", "wt", stdout);
  10.    
  11.     // Чтение графа, G - матрица смежности    
  12.     int nVert, type;
  13.     scanf("%d %d", &nVert, &type);
  14.  
  15.     std::vector<std::vector<bool>> G(nVert, std::vector<bool>(nVert, false));
  16.     for (int i = 0; i < nVert; ++i) {
  17.         char buf[2001];
  18.         scanf("%2000s", buf);
  19.         for (int j = 0; j < nVert; ++j) {
  20.             G[i][j] = (buf[j] == '+');
  21.         }
  22.     }
  23.     // Топологическая сортировка вершин графа:
  24.     std::vector<bool> used;
  25.     used.assign(nVert, false);
  26.     std::vector<int> order;
  27.     for (int i = 0; i < nVert; ++i)
  28.         if (!used[i]) {
  29.             std::function<void(int)> dfs1 = [&dfs1, &used, &G, &order](int curr) {
  30.                 used[curr] = true;
  31.                 for (int next = 0; next < (int)G[curr].size(); ++next)
  32.                     if (G[curr][next] && !used[next]) {
  33.                         dfs1(next);
  34.                     }
  35.                 order.push_back(curr);
  36.             };
  37.             dfs1(i);
  38.         }
  39.     // Получение компонент сильной связности в явном виде:
  40.     used.assign(nVert, false);
  41.     std::vector<std::vector<int>> components(1, std::vector<int>());
  42.     for (int i = 0; i < nVert; ++i) {
  43.         int v = order[nVert-1-i];
  44.         if (!used[v]) {
  45.             std::function<void(int)> dfs2 = [&dfs2, &G, &used, &components](int curr) {
  46.                 used[curr] = true;
  47.                 components.back().push_back(curr);
  48.                 for (int next = 0; next < (int)G[curr].size(); ++next)
  49.                     if (G[next][curr] && !used[next])
  50.                         dfs2(next);
  51.             };
  52.             dfs2(v);
  53.             components.push_back(std::vector<int>());
  54.         }
  55.     }
  56.    
  57.     // Подсчет ответа в случае увеличения количества совершенных городов:
  58.     std::vector<int> count(1+nVert, 0);
  59.     {
  60.         int sum = (int)components[0].size();
  61.         for (int i = 1; i < (int)components.size(); ++i) {
  62.             sum += components[i].size();
  63.             if (sum != 2) {
  64.                 count[sum] += components[0].size() * components[i].size();
  65.             }
  66.         }
  67.     }
  68.    
  69.     // Получение Гамильтонова пути:
  70.     std::vector<int> path;
  71.     for (const auto & v : components[0]) {
  72.         if (path.empty()) {
  73.             path.push_back(v);    
  74.         } else {
  75.             auto it = path.begin();
  76.             while (it != path.end() && G[*it][v]) {
  77.                 ++it;
  78.             }
  79.             path.insert(it, v);
  80.         }
  81.     }
  82.    
  83.     // Проверка того, что Гамильтонов путь был получен корректно (на всякий случай):
  84.     for (int i = 1; i < (int)path.size(); ++i) {
  85.         int prev = path[i-1], curr = path[i];
  86.         assert(G[prev][curr]);
  87.     }
  88.    
  89.     // Гамильтонов цикл:
  90.     std::vector<int> cycle;
  91.     { // Первоначальная подготовка к преобразования Гамильтонова пути в Гамильтонов цикл:
  92.         int start = path[0], i;        
  93.         for (i = (int)path.size()-1; i >= 2; --i) {
  94.             if (G[path[i]][start]) {
  95.                 break;
  96.             }
  97.         }
  98.         cycle.insert(cycle.begin(), path.begin(), path.begin()+i+1);
  99.         path.erase(path.begin(), path.begin()+i+1);
  100.     }
  101.    
  102.     // Преобразование Гамильтонова пути к Гамильтонову циклу:
  103.     for (auto st = path.begin(); st != path.end(); ) {
  104.         auto it = cycle.begin();
  105.         while (it != cycle.end() && G[*it][*st]) {
  106.             ++it;
  107.         }
  108.         if (it != cycle.end()) {
  109.             cycle.insert(it, path.begin(), st+1);
  110.             path.erase(path.begin(), st+1);
  111.             st = path.begin();
  112.         } else {
  113.             st++;
  114.         }
  115.     }
  116.    
  117.     if ((int)cycle.size() > 1) // Проверяем, что был найден цикл (на всякий случай)
  118.         for (int i = 0, n = (int)cycle.size(); i < n; ++i) {
  119.             assert(G[cycle[i]][cycle[(i+1) % n]]);
  120.         }
  121.    
  122.     // Проход по ребрам Гамильтонова цикла с разворотом ребер на нем:    
  123.     if ((int)cycle.size() > 1) {
  124.         G[cycle.front()][cycle.back()] = true;
  125.         G[cycle.back()][cycle.front()] = false;
  126.         int n = (int)cycle.size();
  127.         std::vector<int> x(n, -1);
  128.         for (int i = 0; i < n; ++i) {
  129.             for (int j = i+1; j < n; ++j) {
  130.                 int a = cycle[i];
  131.                 int b = cycle[j];
  132.                 if (G[b][a]) {
  133.                     x[i] = j;
  134.                 }
  135.             }
  136.         }        
  137.         bool wasBreaked = false;
  138.         int max = 0;
  139.         for (int i = 0; i < n; ++i) {
  140.             max = std::max(max, x[i]);
  141.             if (max <= i) {
  142.                 count[i+1]++;
  143.                 wasBreaked = true;
  144.                 break;
  145.             }
  146.         }
  147.         assert(wasBreaked);
  148.        
  149.         G[cycle.front()][cycle.back()] = false;
  150.         G[cycle.back()][cycle.front()] = true;
  151.        
  152.         for (int k = 0; k < n-1; ++k) {
  153.             std::rotate(cycle.begin(), cycle.begin()+1, cycle.end());
  154.             for (int i = 0; i+1 < n; ++i) {
  155.                 x[i] = x[i+1] - 1;
  156.             }
  157.             x[n-1] = -1;
  158.             G[cycle.front()][cycle.back()] = true;
  159.             G[cycle.back()][cycle.front()] = false;
  160.            
  161.             for (int i = 0; i < n; ++i) {
  162.                 int a = cycle[i];
  163.                 int b = cycle.back();
  164.                 if (G[b][a]) {
  165.                     x[i] = n-1;
  166.                 }
  167.             }
  168.            
  169.             bool wasBreaked = false;
  170.             int max = 0;
  171.             for (int i = 0; i < n; ++i) {
  172.                 max = std::max(max, x[i]);
  173.                 if (max <= i) {
  174.                     count[i+1]++;
  175.                     wasBreaked = true;
  176.                     break;
  177.                 }
  178.             }
  179.             assert(wasBreaked);
  180.            
  181.             G[cycle.front()][cycle.back()] = false;
  182.             G[cycle.back()][cycle.front()] = true;    
  183.         }
  184.     }
  185.     // Окончательно досчитываем ответ:
  186.     std::vector<bool> is_first_component(nVert, false);
  187.     for (auto & v : components[0]) {
  188.         is_first_component[v] = true;
  189.     }
  190.     for (int i = 0; i < nVert; ++i) {
  191.         for (int j = i+1; j < nVert; ++j) {
  192.             if (!is_first_component[i] && !is_first_component[j]) {
  193.                 count[(int)components.front().size()]++;
  194.             }
  195.         }
  196.     }
  197.     int sum = 0;
  198.     for (int i = 1; i <= nVert; ++i) {
  199.         sum += count[i];
  200.     }
  201.    
  202.     count[(int)components.front().size()] += nVert * (nVert-1)/2 - sum;
  203.     // И выводим его:
  204.     printf("%d\n", (int)components.front().size());
  205.     for (int i = (type == 0 ? (int)components[0].size() : 0)+1; i <= nVert; ++i) {
  206.         printf("%d ", count[i]);
  207.     }
  208.     return 0;
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement