#include <bits/stdc++.h>
#define FOR(i, a, b) for(int i = (int)a; i <= (int)b; ++i)
#define RFOR(i, a, b) for(int i = (int)a; i >= (int)b; --i)
#define in insert
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
using namespace std;
const int MAX = 1e5 + 7;
vector<int> kl[MAX];
vector<int> g[MAX];
int wlk[MAX], rep[MAX], ilk[MAX], jk[MAX];
bool vis[MAX], ons[MAX];
unordered_map<int, int> mapka[MAX];
int ile;
int Find(int x) {
if(x == rep[x]) return x;
rep[x] = Find(rep[x]);
return rep[x];
}
void Union(int a, int b) {
a = Find(a), b = Find(b);
if(a == b) return;
--ilk[jk[a]]; --ile;
if(wlk[a] < wlk[b]) {
wlk[b] += wlk[a];
rep[a] = b;
} else {
wlk[a] += wlk[b];
rep[b] = a;
}
}
//vis -> (true)komponenty rozwazone, (false)nierozwazone
int gc() {
char x;
while(true) {
x = getchar_unlocked();
if(x >= '0' && x <= '9') break;
}
int num = x - '0';
while(true) {
x = getchar_unlocked();
if(x >= '0' && x <= '9') {
num *= 10;
num += (x - '0');
} else break;
}
return num;
}
void solve() {
int n = gc(), m = gc(), k = gc();
//prep
FOR(i, 1, n) {
g[i].clear();
jk[i] = 0;
rep[i] = i;
wlk[i] = 1;
vis[i] = false;
mapka[i].clear();
}
FOR(i, 1, k) {
kl[i].clear();
ilk[i] = 0;
ons[i] = false;
}
ile = n;
//wczytaj
FOR(i, 1, n) {
int x = gc();
kl[x].pb(i);
jk[i] = x;
++ilk[x];
}
//laczenie tych samych kolorow
FOR(i, 1, m) {
int a = gc(), b = gc();
g[a].pb(b), g[b].pb(a);
if(jk[a] == jk[b]) Union(a, b);
}
queue<int> nr; bool tf = true;
FOR(i, 1, n) if(ilk[jk[i]] == 1 && !ons[jk[i]]) {
nr.push(Find(i));
ons[jk[i]] = true;
}
while(!nr.empty()) {
int akt = Find(nr.front()); nr.pop();
if(vis[akt]) continue;
set<int> sasiedzi;
for(int v : kl[jk[akt]]) {
for(int u : g[v]) {
int zt = Find(u);
if(zt != akt) sasiedzi.insert(zt);
}
}
for(int zt : sasiedzi) {
zt = Find(zt);
akt = Find(akt);
if(zt == akt) continue;
//tutaj mergowanie aktualnie usuwanego do juz usunietego. w elsie jest mergowanie aktualnie usuwanego do jeszcze nie usunietego.
if(vis[zt]) {
if(mapka[zt].size() < mapka[akt].size()) {
rep[zt] = akt;
wlk[akt] += wlk[zt];
for(auto g : mapka[zt]) {
if(!mapka[akt][g.fi]) mapka[akt][g.fi] = g.se;
else {
Union(g.se, mapka[akt][g.fi]);
int lid = Find(g.se);
mapka[akt][g.fi] = lid;
if(ilk[jk[lid]] == 1 && !ons[jk[lid]]) {
nr.push(lid);
ons[jk[lid]] = true;
}
}
}
} else {
rep[akt] = zt;
wlk[zt] += wlk[akt];
for(auto g : mapka[akt]) {
if(!mapka[zt][g.fi]) mapka[zt][g.fi] = g.se;
else {
Union(g.se, mapka[zt][g.fi]);
int lid = Find(g.se);
mapka[zt][g.fi] = lid;
if(ilk[jk[lid]] == 1 && !ons[jk[lid]]) {
nr.push(lid);
ons[jk[lid]] = true;
}
}
}
}
} else {
if(!mapka[akt][jk[zt]]) {
mapka[akt][jk[zt]] = Find(zt);
} else {
Union(mapka[akt][jk[zt]], zt);
int lid = Find(zt);
mapka[akt][jk[zt]] = lid;
if(ilk[jk[lid]] == 1 && !ons[jk[lid]]) {
nr.push(lid);
ons[jk[lid]] = true;
}
}
}
}
vis[akt] = true; --ile;
}
if(ile != 0) tf = false;
if(tf) cout << "TAK\n";
else cout << "NIE\n";
}
int main() {
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int t = gc();
while(t--) solve();
return 0;
}
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 163 164 165 166 | #include <bits/stdc++.h> #define FOR(i, a, b) for(int i = (int)a; i <= (int)b; ++i) #define RFOR(i, a, b) for(int i = (int)a; i >= (int)b; --i) #define in insert #define pb push_back #define fi first #define se second #define ll long long #define ull unsigned long long using namespace std; const int MAX = 1e5 + 7; vector<int> kl[MAX]; vector<int> g[MAX]; int wlk[MAX], rep[MAX], ilk[MAX], jk[MAX]; bool vis[MAX], ons[MAX]; unordered_map<int, int> mapka[MAX]; int ile; int Find(int x) { if(x == rep[x]) return x; rep[x] = Find(rep[x]); return rep[x]; } void Union(int a, int b) { a = Find(a), b = Find(b); if(a == b) return; --ilk[jk[a]]; --ile; if(wlk[a] < wlk[b]) { wlk[b] += wlk[a]; rep[a] = b; } else { wlk[a] += wlk[b]; rep[b] = a; } } //vis -> (true)komponenty rozwazone, (false)nierozwazone int gc() { char x; while(true) { x = getchar_unlocked(); if(x >= '0' && x <= '9') break; } int num = x - '0'; while(true) { x = getchar_unlocked(); if(x >= '0' && x <= '9') { num *= 10; num += (x - '0'); } else break; } return num; } void solve() { int n = gc(), m = gc(), k = gc(); //prep FOR(i, 1, n) { g[i].clear(); jk[i] = 0; rep[i] = i; wlk[i] = 1; vis[i] = false; mapka[i].clear(); } FOR(i, 1, k) { kl[i].clear(); ilk[i] = 0; ons[i] = false; } ile = n; //wczytaj FOR(i, 1, n) { int x = gc(); kl[x].pb(i); jk[i] = x; ++ilk[x]; } //laczenie tych samych kolorow FOR(i, 1, m) { int a = gc(), b = gc(); g[a].pb(b), g[b].pb(a); if(jk[a] == jk[b]) Union(a, b); } queue<int> nr; bool tf = true; FOR(i, 1, n) if(ilk[jk[i]] == 1 && !ons[jk[i]]) { nr.push(Find(i)); ons[jk[i]] = true; } while(!nr.empty()) { int akt = Find(nr.front()); nr.pop(); if(vis[akt]) continue; set<int> sasiedzi; for(int v : kl[jk[akt]]) { for(int u : g[v]) { int zt = Find(u); if(zt != akt) sasiedzi.insert(zt); } } for(int zt : sasiedzi) { zt = Find(zt); akt = Find(akt); if(zt == akt) continue; //tutaj mergowanie aktualnie usuwanego do juz usunietego. w elsie jest mergowanie aktualnie usuwanego do jeszcze nie usunietego. if(vis[zt]) { if(mapka[zt].size() < mapka[akt].size()) { rep[zt] = akt; wlk[akt] += wlk[zt]; for(auto g : mapka[zt]) { if(!mapka[akt][g.fi]) mapka[akt][g.fi] = g.se; else { Union(g.se, mapka[akt][g.fi]); int lid = Find(g.se); mapka[akt][g.fi] = lid; if(ilk[jk[lid]] == 1 && !ons[jk[lid]]) { nr.push(lid); ons[jk[lid]] = true; } } } } else { rep[akt] = zt; wlk[zt] += wlk[akt]; for(auto g : mapka[akt]) { if(!mapka[zt][g.fi]) mapka[zt][g.fi] = g.se; else { Union(g.se, mapka[zt][g.fi]); int lid = Find(g.se); mapka[zt][g.fi] = lid; if(ilk[jk[lid]] == 1 && !ons[jk[lid]]) { nr.push(lid); ons[jk[lid]] = true; } } } } } else { if(!mapka[akt][jk[zt]]) { mapka[akt][jk[zt]] = Find(zt); } else { Union(mapka[akt][jk[zt]], zt); int lid = Find(zt); mapka[akt][jk[zt]] = lid; if(ilk[jk[lid]] == 1 && !ons[jk[lid]]) { nr.push(lid); ons[jk[lid]] = true; } } } } vis[akt] = true; --ile; } if(ile != 0) tf = false; if(tf) cout << "TAK\n"; else cout << "NIE\n"; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int t = gc(); while(t--) solve(); return 0; } |
English