#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define st first
#define nd second
vector<int> rep, sz;
vector<int> super_rep;
vector<map<int, int>> supernodes;
vector<vector<int>> supernode_g;
vector<int> number_of_comp;
queue<int> ones;
vector<bool> vis;
int Find(int u) {
if (rep[u] != u) rep[u] = Find(rep[u]);
return rep[u];
}
void Union(int u, int v) {
u = Find(u), v = Find(v);
if (sz[u] > sz[v]) swap(u, v);
sz[v] += sz[u];
rep[u] = v;
}
int super_merge(int u, int v) {
// cout << "merging " << u << " and " << v << endl;
if (u == v) return u;
if (supernodes[u].size() > supernodes[v].size()) swap(u, v);
for (auto p: supernodes[u]) {
if (vis[p.nd]) continue;
if (supernodes[v].find(p.st) != supernodes[v].end()) {
if (Find(supernodes[u][p.st]) != Find(supernodes[v][p.st])) {
Union(supernodes[u][p.st], supernodes[v][p.st]);
number_of_comp[p.st]--;
if (number_of_comp[p.st] == 1) ones.push(p.st);
}
// supernodes[v][p.st] = Find
}
else {
supernodes[v][p.st] = p.nd;
supernode_g[p.nd].push_back(v);
}
}
// supernodes[u].clear();
// supernodes[u].
supernodes[u] = map<int, int>();
return v;
}
void solve(int t) {
int n, m, k; cin >> n >> m >> k;
// if (t) cout << n << ' ' << m << ' ' << k << '\n';
number_of_comp = vector<int>(k+1);
vector<vector<int>> g(n+1);
vector<int> col(n+1);
vector<vector<int>> nodes_of_col(k+1);
supernode_g = vector<vector<int>>(n+1);
supernodes = vector<map<int, int>>(k+1);
super_rep = vector<int>(k+1);
rep = vector<int>(n+1);
sz = vector<int>(n+1);
vis = vector<bool>(n+1);
ones = queue<int>();
for (int i = 1; i <= n; i++) {
cin >> col[i];
// if (t) cout << col[i] << ' ';
number_of_comp[col[i]]++;
nodes_of_col[col[i]].push_back(i);
rep[i] = i;
sz[i] = 1;
}
// if (t) cout << '\n';
for (int i = 0; i < m; i++) {
int u, v; cin >> u >> v;
// if (t == 17) cout << u << ' ' << v << '\n';
g[u].push_back(v);
g[v].push_back(u);
if (col[u] == col[v]) {
if (Find(u) != Find(v)) {
Union(u, v);
number_of_comp[col[u]]--;
}
}
}
for (int i = 1; i <= k; i++) {
// cout << number_of_comp[i] << ' ';
if (number_of_comp[i] == 1) ones.push(i);
super_rep[i] = i;
supernodes[i].clear();
}
// cout << '\n';
vector<int> prev_edge(k+1);
queue<int> colors_touched;
while (!ones.empty()) {
int c = ones.front();
ones.pop();
// cout << c << endl;
for (int u: nodes_of_col[c]) {
vis[u] = true;
for (int v: g[u]) {
if (vis[v] || col[v] == c) continue;
if (prev_edge[col[v]] == 0) {
prev_edge[col[v]] = v;
colors_touched.push(col[v]);
}
else {
if (Find(v) != Find(prev_edge[col[v]])) {
Union(v, prev_edge[col[v]]);
number_of_comp[col[v]]--;
if (number_of_comp[col[v]] == 1) ones.push(col[v]);
}
}
}
}
while (!colors_touched.empty()) {
int u = prev_edge[colors_touched.front()];
supernodes[c][colors_touched.front()] = Find(u);
supernode_g[Find(u)].push_back(c);
prev_edge[colors_touched.front()] = 0;
colors_touched.pop();
}
// for (auto p: supernodes[c]) {
// cout << p.st << ' ' << p.nd << endl;
// }
int cur_super = c;
for (int u: nodes_of_col[c]) {
for (int s: supernode_g[u]) {
// cout << "s: " << s << endl;
cur_super = super_merge(cur_super, s);
}
}
}
for (int i = 1; i <= k; i++) {
if (number_of_comp[i] > 1) {
cout << "NIE" << "\n";
return;
}
}
cout << "TAK" << "\n";
return;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
int t = 1;
cin >> t;
while (t--) {
solve(t);
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; #define st first #define nd second vector<int> rep, sz; vector<int> super_rep; vector<map<int, int>> supernodes; vector<vector<int>> supernode_g; vector<int> number_of_comp; queue<int> ones; vector<bool> vis; int Find(int u) { if (rep[u] != u) rep[u] = Find(rep[u]); return rep[u]; } void Union(int u, int v) { u = Find(u), v = Find(v); if (sz[u] > sz[v]) swap(u, v); sz[v] += sz[u]; rep[u] = v; } int super_merge(int u, int v) { // cout << "merging " << u << " and " << v << endl; if (u == v) return u; if (supernodes[u].size() > supernodes[v].size()) swap(u, v); for (auto p: supernodes[u]) { if (vis[p.nd]) continue; if (supernodes[v].find(p.st) != supernodes[v].end()) { if (Find(supernodes[u][p.st]) != Find(supernodes[v][p.st])) { Union(supernodes[u][p.st], supernodes[v][p.st]); number_of_comp[p.st]--; if (number_of_comp[p.st] == 1) ones.push(p.st); } // supernodes[v][p.st] = Find } else { supernodes[v][p.st] = p.nd; supernode_g[p.nd].push_back(v); } } // supernodes[u].clear(); // supernodes[u]. supernodes[u] = map<int, int>(); return v; } void solve(int t) { int n, m, k; cin >> n >> m >> k; // if (t) cout << n << ' ' << m << ' ' << k << '\n'; number_of_comp = vector<int>(k+1); vector<vector<int>> g(n+1); vector<int> col(n+1); vector<vector<int>> nodes_of_col(k+1); supernode_g = vector<vector<int>>(n+1); supernodes = vector<map<int, int>>(k+1); super_rep = vector<int>(k+1); rep = vector<int>(n+1); sz = vector<int>(n+1); vis = vector<bool>(n+1); ones = queue<int>(); for (int i = 1; i <= n; i++) { cin >> col[i]; // if (t) cout << col[i] << ' '; number_of_comp[col[i]]++; nodes_of_col[col[i]].push_back(i); rep[i] = i; sz[i] = 1; } // if (t) cout << '\n'; for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; // if (t == 17) cout << u << ' ' << v << '\n'; g[u].push_back(v); g[v].push_back(u); if (col[u] == col[v]) { if (Find(u) != Find(v)) { Union(u, v); number_of_comp[col[u]]--; } } } for (int i = 1; i <= k; i++) { // cout << number_of_comp[i] << ' '; if (number_of_comp[i] == 1) ones.push(i); super_rep[i] = i; supernodes[i].clear(); } // cout << '\n'; vector<int> prev_edge(k+1); queue<int> colors_touched; while (!ones.empty()) { int c = ones.front(); ones.pop(); // cout << c << endl; for (int u: nodes_of_col[c]) { vis[u] = true; for (int v: g[u]) { if (vis[v] || col[v] == c) continue; if (prev_edge[col[v]] == 0) { prev_edge[col[v]] = v; colors_touched.push(col[v]); } else { if (Find(v) != Find(prev_edge[col[v]])) { Union(v, prev_edge[col[v]]); number_of_comp[col[v]]--; if (number_of_comp[col[v]] == 1) ones.push(col[v]); } } } } while (!colors_touched.empty()) { int u = prev_edge[colors_touched.front()]; supernodes[c][colors_touched.front()] = Find(u); supernode_g[Find(u)].push_back(c); prev_edge[colors_touched.front()] = 0; colors_touched.pop(); } // for (auto p: supernodes[c]) { // cout << p.st << ' ' << p.nd << endl; // } int cur_super = c; for (int u: nodes_of_col[c]) { for (int s: supernode_g[u]) { // cout << "s: " << s << endl; cur_super = super_merge(cur_super, s); } } } for (int i = 1; i <= k; i++) { if (number_of_comp[i] > 1) { cout << "NIE" << "\n"; return; } } cout << "TAK" << "\n"; return; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); int t = 1; cin >> t; while (t--) { solve(t); } } |
English