Advertisement
Dang_Quan_10_Tin

Coronation

Dec 1st, 2020
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.50 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. using ld = long double;
  5. using ull = unsigned long long;
  6.  
  7. bool typetest;
  8. inline void fastIOfileinput()
  9. {
  10.     ios::sync_with_stdio(0);
  11.     cin.tie(0);
  12.     cout.tie(0);
  13.     typetest = 1;
  14. }
  15.  
  16. const int N = 50 + 2;
  17. int n, m, k;
  18. /// a[] và ra[]: Đổi string ra biến số để tiện dùng toán tử &
  19. /// a[] = S, ra[] = S'
  20. ull a[N], ra[N];
  21. /// Danh sách liên thuộc: first: đỉnh đến
  22. ///                       second: trọng số cạnh
  23. vector<pair<int, int>> adj[N];
  24. bool ck[N];
  25. /// b[]: Mảng màu của đỉnh, b[i] = -1 nghĩa là chưa tô màu (*)
  26. /// cnt[i][j]: Số lượng đỉnh màu j trong thành phần liên thông i
  27. /// l là thành phần liên thông hiện tại
  28. int b[N], l, cnt[N][2];
  29. /// ans: Là những thằng được chọn để đảo ngược
  30. vector<int> ans;
  31.  
  32. void Read()
  33. {
  34.     l = 0;
  35.     ans.clear();
  36.     for (int i = 0; i <= 50; ++i)
  37.     {
  38.         ck[i] = 0;
  39.         /// Xóa màu, xóa liên thông
  40.         b[i] = -1;
  41.         cnt[i][0] = 0;
  42.         cnt[i][1] = 0;
  43.         adj[i].clear();
  44.         a[i] = ra[i] = 0;
  45.     }
  46.     cin >> n >> m >> k;
  47.     for (int i = 1; i <= n; ++i)
  48.     {
  49.         string s;
  50.         cin >> s;
  51.         /// Đổi xâu sang số
  52.         for (int j = 0; j < m; ++j)
  53.             if (s[j] == '1')
  54.                 a[i] |= 1ll << j;
  55.         /// Xâu đảo ngược
  56.         reverse(s.begin(), s.end());
  57.         for (int j = 0; j < m; ++j)
  58.             if (s[j] == '1')
  59.                 ra[i] |= 1ll << j;
  60.     }
  61. }
  62.  
  63. /// Đọc hàm Solve đi đã
  64. /// Hàm tô màu, trả về kiểu bool: 1 nghĩa là tô được, 0 nghĩa là xảy ra xung đột
  65. bool dfs(int v, int col = 0)
  66. {
  67.     /// Màu mới, tăng biến đếm màu
  68.     b[v] = col;
  69.     ++cnt[l][col];
  70.     for (auto i : adj[v])
  71.         /// Nếu chưa tô
  72.         if (b[i.first] == -1)
  73.         {
  74.             /// Xung đột => Dừng tô màu
  75.             if (!dfs(i.first, col ^ i.second)) /// (*) Nếu i.second = 0 nghĩa là 2 đỉnh cùng màu, 1 nghĩa là 2 đỉnh khác màu
  76.                 return false;
  77.         }
  78.         /// Nếu có xung đột, bé bẻ gãy bút màu
  79.         else if (b[i.first] != (col ^ i.second))
  80.             return false;
  81.     /// Oke, tô màu thành công
  82.     return true;
  83. }
  84.  
  85. /// Đọc hàm Solve đi đã
  86. /// Truy vết lấy đáp án
  87. void GetAns(int v, const int &col)
  88. {
  89.     if (b[v] == col)
  90.         ans.push_back(v);
  91.     ck[v] = 1;
  92.     for (auto i : adj[v])
  93.         if (!ck[i.first])
  94.             GetAns(i.first, col);
  95. }
  96.  
  97. void Solve()
  98. {
  99. /// Tạo cạnh cho đồ thị
  100.     for (int i = 1; i <= n; ++i) // Duyệt các đỉnh
  101.         for (int j = 1; j < i; ++j) // Duyệt các đỉnh
  102.         {
  103.             /// Nếu như S[i] = S[j]
  104.             if (__builtin_popcountll(a[i] ^ a[j]) <= m - k)
  105.             {
  106.                 /// Nếu như S[i] != S'[j], thêm cạnh có trọng số 0 (Hai đỉnh cùng màu)
  107.                 if (__builtin_popcountll(a[i] ^ ra[j]) > m - k)
  108.                 {
  109.                     adj[i].push_back({j, 0});
  110.                     adj[j].push_back({i, 0});
  111.                 }
  112.             }
  113.             /// Nếu như S[i] = S'[j], thêm cạnh có trọng số 1 (Hai đỉnh khác màu)
  114.             else if (__builtin_popcountll(a[i] ^ ra[j]) <= m - k)
  115.             {
  116.                 adj[i].push_back({j, 1});
  117.                 adj[j].push_back({i, 1});
  118.             }
  119.             /// Hai con này thích đánh nhau, không ngăn được
  120.             else
  121.             {
  122.                 cout << "-1\n";
  123.                 return;
  124.             }
  125.         }
  126.     /// Bé tập tô màu đồ thị
  127.     for (int i = 1; i <= n; ++i)
  128.         /// (*)Nếu chưa tô
  129.         if (b[i] == -1)
  130.         {
  131.             /// Thành phần liên thông mới
  132.             ++l;
  133.             /// Nếu xảy ra xung đột (Đọc hàm dfs)
  134.             if (!dfs(i))
  135.             {
  136.                 cout << -1 << "\n";
  137.                 return;
  138.             }
  139.             /// Tham bẩn, chọn màu có số lượng ít hơn (Đọc hàm GetAns)
  140.             if (cnt[l][0] > cnt[l][1])
  141.                 GetAns(i, 1);
  142.             else
  143.                 GetAns(i, 0);
  144.         }
  145.     /// In ra
  146.     cout << ans.size() << "\n";
  147.     for (auto i : ans)
  148.         cout << i << " ";
  149.     cout << "\n";
  150. }
  151.  
  152. int32_t main()
  153. {
  154.     fastIOfileinput();
  155.     if (typetest)
  156.     {
  157.         int t;
  158.         cin >> t;
  159.         for (int v = 1; v <= t; ++v)
  160.         {
  161.             Read();
  162.             Solve();
  163.         }
  164.     }
  165.     else
  166.     {
  167.         Read();
  168.         Solve();
  169.     }
  170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement