#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define st first
#define nd second
#define pb push_back
#define all(a) a.begin(), a.end()
#define sz(a) int(a.size())
#define f(i, a, b) for (int i = a; i < b; i++)
#define rep(i, a) f(i, 0, a)
#define int ll
#define tv(a, x) for (auto& a : x)
#define DUZO 1000000000000000000LL
#define en "\n"
#define cn continue
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;
using vii = vector<pii>;
int n, m, k;
vvi spojne; //jakie wierzcholki sa w tej spojnej
vi jk; //w jakiej spojenej
vvi g;
vi a; //jaka partia tu wygrala
vi odw;
vi szef;
vi do_usuniecia;
vector<unordered_map<int, int>> sasd_pustych; //ujemne to znaczy ze tyle razy wystapil dany kolor a nieujmne to numer spojnej ktorea sasdiuje z tym
vi ile_poslow;
void dfs_wyznacz_spojne(int v) {
odw[v] = 1;
jk[v] = sz(spojne) - 1;
spojne.back().pb(v);
tv(u, g[v]) {
if (a[u] != a[v] || odw[u]) cn;
dfs_wyznacz_spojne(u);
}
}
int fi(int v) {
if (szef[v] == v) return v;
return (szef[v] = fi(szef[v]));
}
void un(int u, int v) {
u = fi(u);
v = fi(v);
if (u == v) return;
if (sz(sasd_pustych[u]) > sz(sasd_pustych[v])) {
swap(u, v);
}
tv(ele, sasd_pustych[u]) {
if (ele.st < 0) cn;
if (sasd_pustych[v].find(ele.st) != sasd_pustych[v].end()) cn; //juz ta spojna podlaczona
sasd_pustych[v][ele.st] = ele.nd; //czyli ze wystapila bo ele.nd = 1 bo nie chce mi sie unor set robic
int kol = a[spojne[ele.st][0]];
sasd_pustych[v][-kol] += sz(spojne[ele.st]);
if (sasd_pustych[v][-kol] == ile_poslow[kol]) {
ile_poslow[kol] = -1;
do_usuniecia.pb(kol);
}
}
szef[u] = v;
}
void solve() {
cin >> n >> m >> k;
g = {};
spojne = {};
jk = {};
a = {};
odw = {};
g.resize(n + 1);
jk.resize(n + 1);
a.resize(n + 1);
odw.resize(n + 1, 0);
f(i, 1, n+ 1) cin >> a[i];
f(i, 0, m) {
int u, v;
cin >> u >> v;
g[u].pb(v);
g[v].pb(u);
}
f(i, 1, n+ 1) {
if (odw[i]) cn;
spojne.pb({});
dfs_wyznacz_spojne(i);
}
//odw teraz to znaczy czy aktywne
int il = 0; //ile usunelismy
do_usuniecia = {};
ile_poslow = {};
ile_poslow.resize(k + 1, 0);
f(i, 1, n+1) ile_poslow[a[i]]++;
f(i, 1, n + 1) {
if (sz(spojne[jk[i]]) == ile_poslow[a[i]]) {
do_usuniecia.pb(a[i]);
ile_poslow[a[i]] = -1; //by tylko raz dalo sie dodac
}
}
vvi gru(k + 1);
f(i, 1, n + 1) {
gru[a[i]].pb(i);
}
szef = {};
szef.resize(n + 1, 0); //0 czyli nie jest aktywowany
sasd_pustych = {};
sasd_pustych.resize(n + 1);
while (sz(do_usuniecia)) {
il++; //zwiekszamy licznik ile usunelismy kolorow
int kol = do_usuniecia.back();
do_usuniecia.pop_back();
int aktl_szef = gru[kol][0];
tv(v, gru[kol]) {
szef[v] = aktl_szef;
}
tv(v, gru[kol]) {
tv(u, g[v]) {
if (!szef[u]) cn; //nieodwiedzone
un(u, v);
}
}
tv(v, gru[kol]) {
tv(u, g[v]) {
if (szef[u]) cn;
//dodajemy randomow
int boss = fi(v);
if (sasd_pustych[boss].find(jk[u]) == sasd_pustych[boss].end()) {
sasd_pustych[boss][jk[u]] = 1;
int kol = a[u];
sasd_pustych[boss][-kol] += sz(spojne[jk[u]]);
if (sasd_pustych[boss][-kol] == ile_poslow[kol]) {
ile_poslow[kol] = -1;
do_usuniecia.pb(kol);
}
}
}
}
}
int ile_zyje = 0;
f(i,1,k + 1) {
if (sz(gru[i])) ile_zyje++;
}
if (ile_zyje == il) {
cout << "TAK\n";
return;
} else {
cout << "NIE\n";
}
}
int32_t main() {
ios::sync_with_stdio(0);
cin.tie(0);
int q = 1;
cin >> q;
while (q--) {
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> using namespace std; typedef long long ll; #define st first #define nd second #define pb push_back #define all(a) a.begin(), a.end() #define sz(a) int(a.size()) #define f(i, a, b) for (int i = a; i < b; i++) #define rep(i, a) f(i, 0, a) #define int ll #define tv(a, x) for (auto& a : x) #define DUZO 1000000000000000000LL #define en "\n" #define cn continue using pii = pair<int, int>; using vi = vector<int>; using vvi = vector<vi>; using vii = vector<pii>; int n, m, k; vvi spojne; //jakie wierzcholki sa w tej spojnej vi jk; //w jakiej spojenej vvi g; vi a; //jaka partia tu wygrala vi odw; vi szef; vi do_usuniecia; vector<unordered_map<int, int>> sasd_pustych; //ujemne to znaczy ze tyle razy wystapil dany kolor a nieujmne to numer spojnej ktorea sasdiuje z tym vi ile_poslow; void dfs_wyznacz_spojne(int v) { odw[v] = 1; jk[v] = sz(spojne) - 1; spojne.back().pb(v); tv(u, g[v]) { if (a[u] != a[v] || odw[u]) cn; dfs_wyznacz_spojne(u); } } int fi(int v) { if (szef[v] == v) return v; return (szef[v] = fi(szef[v])); } void un(int u, int v) { u = fi(u); v = fi(v); if (u == v) return; if (sz(sasd_pustych[u]) > sz(sasd_pustych[v])) { swap(u, v); } tv(ele, sasd_pustych[u]) { if (ele.st < 0) cn; if (sasd_pustych[v].find(ele.st) != sasd_pustych[v].end()) cn; //juz ta spojna podlaczona sasd_pustych[v][ele.st] = ele.nd; //czyli ze wystapila bo ele.nd = 1 bo nie chce mi sie unor set robic int kol = a[spojne[ele.st][0]]; sasd_pustych[v][-kol] += sz(spojne[ele.st]); if (sasd_pustych[v][-kol] == ile_poslow[kol]) { ile_poslow[kol] = -1; do_usuniecia.pb(kol); } } szef[u] = v; } void solve() { cin >> n >> m >> k; g = {}; spojne = {}; jk = {}; a = {}; odw = {}; g.resize(n + 1); jk.resize(n + 1); a.resize(n + 1); odw.resize(n + 1, 0); f(i, 1, n+ 1) cin >> a[i]; f(i, 0, m) { int u, v; cin >> u >> v; g[u].pb(v); g[v].pb(u); } f(i, 1, n+ 1) { if (odw[i]) cn; spojne.pb({}); dfs_wyznacz_spojne(i); } //odw teraz to znaczy czy aktywne int il = 0; //ile usunelismy do_usuniecia = {}; ile_poslow = {}; ile_poslow.resize(k + 1, 0); f(i, 1, n+1) ile_poslow[a[i]]++; f(i, 1, n + 1) { if (sz(spojne[jk[i]]) == ile_poslow[a[i]]) { do_usuniecia.pb(a[i]); ile_poslow[a[i]] = -1; //by tylko raz dalo sie dodac } } vvi gru(k + 1); f(i, 1, n + 1) { gru[a[i]].pb(i); } szef = {}; szef.resize(n + 1, 0); //0 czyli nie jest aktywowany sasd_pustych = {}; sasd_pustych.resize(n + 1); while (sz(do_usuniecia)) { il++; //zwiekszamy licznik ile usunelismy kolorow int kol = do_usuniecia.back(); do_usuniecia.pop_back(); int aktl_szef = gru[kol][0]; tv(v, gru[kol]) { szef[v] = aktl_szef; } tv(v, gru[kol]) { tv(u, g[v]) { if (!szef[u]) cn; //nieodwiedzone un(u, v); } } tv(v, gru[kol]) { tv(u, g[v]) { if (szef[u]) cn; //dodajemy randomow int boss = fi(v); if (sasd_pustych[boss].find(jk[u]) == sasd_pustych[boss].end()) { sasd_pustych[boss][jk[u]] = 1; int kol = a[u]; sasd_pustych[boss][-kol] += sz(spojne[jk[u]]); if (sasd_pustych[boss][-kol] == ile_poslow[kol]) { ile_poslow[kol] = -1; do_usuniecia.pb(kol); } } } } } int ile_zyje = 0; f(i,1,k + 1) { if (sz(gru[i])) ile_zyje++; } if (ile_zyje == il) { cout << "TAK\n"; return; } else { cout << "NIE\n"; } } int32_t main() { ios::sync_with_stdio(0); cin.tie(0); int q = 1; cin >> q; while (q--) { solve(); } return 0; } |
English