Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- using ll = long long;
- using ld = long double;
- using ull = unsigned long long;
- bool typetest;
- inline void fastIOfileinput()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- typetest = 1;
- }
- const int N = 50 + 2;
- int n, m, k;
- /// a[] và ra[]: Đổi string ra biến số để tiện dùng toán tử &
- /// a[] = S, ra[] = S'
- ull a[N], ra[N];
- /// Danh sách liên thuộc: first: đỉnh đến
- /// second: trọng số cạnh
- vector<pair<int, int>> adj[N];
- bool ck[N];
- /// b[]: Mảng màu của đỉnh, b[i] = -1 nghĩa là chưa tô màu (*)
- /// cnt[i][j]: Số lượng đỉnh màu j trong thành phần liên thông i
- /// l là thành phần liên thông hiện tại
- int b[N], l, cnt[N][2];
- /// ans: Là những thằng được chọn để đảo ngược
- vector<int> ans;
- void Read()
- {
- l = 0;
- ans.clear();
- for (int i = 0; i <= 50; ++i)
- {
- ck[i] = 0;
- /// Xóa màu, xóa liên thông
- b[i] = -1;
- cnt[i][0] = 0;
- cnt[i][1] = 0;
- adj[i].clear();
- a[i] = ra[i] = 0;
- }
- cin >> n >> m >> k;
- for (int i = 1; i <= n; ++i)
- {
- string s;
- cin >> s;
- /// Đổi xâu sang số
- for (int j = 0; j < m; ++j)
- if (s[j] == '1')
- a[i] |= 1ll << j;
- /// Xâu đảo ngược
- reverse(s.begin(), s.end());
- for (int j = 0; j < m; ++j)
- if (s[j] == '1')
- ra[i] |= 1ll << j;
- }
- }
- /// Đọc hàm Solve đi đã
- /// 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
- bool dfs(int v, int col = 0)
- {
- /// Màu mới, tăng biến đếm màu
- b[v] = col;
- ++cnt[l][col];
- for (auto i : adj[v])
- /// Nếu chưa tô
- if (b[i.first] == -1)
- {
- /// Xung đột => Dừng tô màu
- 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
- return false;
- }
- /// Nếu có xung đột, bé bẻ gãy bút màu
- else if (b[i.first] != (col ^ i.second))
- return false;
- /// Oke, tô màu thành công
- return true;
- }
- /// Đọc hàm Solve đi đã
- /// Truy vết lấy đáp án
- void GetAns(int v, const int &col)
- {
- if (b[v] == col)
- ans.push_back(v);
- ck[v] = 1;
- for (auto i : adj[v])
- if (!ck[i.first])
- GetAns(i.first, col);
- }
- void Solve()
- {
- /// Tạo cạnh cho đồ thị
- for (int i = 1; i <= n; ++i) // Duyệt các đỉnh
- for (int j = 1; j < i; ++j) // Duyệt các đỉnh
- {
- /// Nếu như S[i] = S[j]
- if (__builtin_popcountll(a[i] ^ a[j]) <= m - k)
- {
- /// Nếu như S[i] != S'[j], thêm cạnh có trọng số 0 (Hai đỉnh cùng màu)
- if (__builtin_popcountll(a[i] ^ ra[j]) > m - k)
- {
- adj[i].push_back({j, 0});
- adj[j].push_back({i, 0});
- }
- }
- /// Nếu như S[i] = S'[j], thêm cạnh có trọng số 1 (Hai đỉnh khác màu)
- else if (__builtin_popcountll(a[i] ^ ra[j]) <= m - k)
- {
- adj[i].push_back({j, 1});
- adj[j].push_back({i, 1});
- }
- /// Hai con này thích đánh nhau, không ngăn được
- else
- {
- cout << "-1\n";
- return;
- }
- }
- /// Bé tập tô màu đồ thị
- for (int i = 1; i <= n; ++i)
- /// (*)Nếu chưa tô
- if (b[i] == -1)
- {
- /// Thành phần liên thông mới
- ++l;
- /// Nếu xảy ra xung đột (Đọc hàm dfs)
- if (!dfs(i))
- {
- cout << -1 << "\n";
- return;
- }
- /// Tham bẩn, chọn màu có số lượng ít hơn (Đọc hàm GetAns)
- if (cnt[l][0] > cnt[l][1])
- GetAns(i, 1);
- else
- GetAns(i, 0);
- }
- /// In ra
- cout << ans.size() << "\n";
- for (auto i : ans)
- cout << i << " ";
- cout << "\n";
- }
- int32_t main()
- {
- fastIOfileinput();
- if (typetest)
- {
- int t;
- cin >> t;
- for (int v = 1; v <= t; ++v)
- {
- Read();
- Solve();
- }
- }
- else
- {
- Read();
- Solve();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement