#include <bits/stdc++.h>
#define ll long long
#define pi std::pair<int, int>
#define pll std::pair<ll, ll>
#define vi std::vector<int>
#define vll std::vector<ll>
#define vpi std::vector<pi>
#define vpll std::vector<pll>
#define si std::set<int>
// no moja logika byla bledna
// a ja odkrylem ze umiem czytac ale nie umiem interpretowac
// a przynajmniej mam nadzieje ze nie umiem
// i zloznosc logarytmiczno liniowa przechodzi
// wiec robilbym dsu bez optymalizacji sciezkowej
// i laczac sprawdzalbym czy wszystkie miasta naleza do jednego dsu, sa laczne, a wiec beda tworzyc krawedzie
// musze jakos rozrozniac laczenie
// chce laczyc rozne kolory, gdy sa calkowicie spojne
// zas te same kolory powinienem laczyc caly czas
// jak sie jakis kolor uspojni to powinienem tez moc polaczyc te same kolory ale nie rozne
// no i przesadzilem troszeczke i moj kod nawet nie spelnia zalozen
int find(int x, vi &leader)
{
if (leader[x] == x)
return x;
return leader[x] = find(leader[x], leader); // zwykly find
}
void join(int x, int y, vi &leader, std::stack<int> &to_join, vi &groups, std::vector<vi> &rep, vi &wyn, std::vector<bool> &done)
{
x = find(x, leader);
y = find(y, leader);
if (x == y)
return;
if (groups[x] < groups[y])
std::swap(x, y);
groups[x] += groups[y];
leader[y] = x;
if (groups[x] == rep[wyn[x]].size() && !done[wyn[x]])
{
done[wyn[x]] = true;
to_join.push(wyn[x]);
}
}
void colorjoin(int x, int y, vi &cleader, std::vector<std::map<int, int>> &neighs, std::vector<bool> &done, std::stack<int> &to_join, vi &groups, std::vector<vi> &rep, vi &wyn, vi &leader)
{
x = find(x, cleader);
y = find(y, cleader);
if (x == y)
return;
if (neighs[x].size() < neighs[y].size())
std::swap(x, y);
cleader[y] = x; // o tym tez wypadaloby nie zapominac
for (auto &el : neighs[y])
if (!done[el.first])
{
if (neighs[x].find(el.first) == neighs[x].end()) // jezeli moge przekopiowac sasiada to to robie
neighs[x][el.first] = el.second;
else
join(neighs[x][el.first], el.second, leader, to_join, groups, rep, wyn, done); // jezeli zas kolory maja sasiadow, o tym samym kolorze, to moga nie byc polaczone a polaczenie jest przez te spojne, co oznacza ze moge polaczyc
}
}
void solve()
{
int n, m, k;
std::cin >> n >> m >> k;
std::vector<bool> visited(n + 1), done(k + 1);
vi wyn(n + 1), count(k + 1), leader(n + 1), groups(n + 1), cleader(k + 1);
std::vector<vi> rep(k + 1), links(n + 1);
std::stack<int> to_join;
std::vector<std::map<int, int>> neighs(k + 1);
for (int i = 1; i <= n; i++)
{
leader[i] = i;
groups[i] = 1;
}
for (int i = 1; i <= k; i++)
cleader[i] = i;
for (int i = 1; i <= n; i++)
{
std::cin >> wyn[i];
rep[wyn[i]].push_back(i);
}
int a, b;
for (int i = 0; i < m; i++)
{
std::cin >> a >> b;
links[a].push_back(b);
links[b].push_back(a);
if (wyn[a] == wyn[b])
join(a, b, leader, to_join, groups, rep, wyn, done);
}
for (int i = 1; i <= k; i++)
{
if (rep[i].size() <= 1)
done[i] = true;
if (rep[i].size() == 1)
to_join.push(i);
}
while (!to_join.empty())
{
int x = to_join.top();
to_join.pop();
for (auto &jel : rep[x])
for (auto &el : links[jel])
{
if (wyn[el] != x)
{
if (done[wyn[el]])
colorjoin(wyn[el], x, cleader, neighs, done, to_join, groups, rep, wyn, leader); // lacze kolory nie kolor z wierzcholkiem
else // jezeli sasiad jest niespojny, no to przyda sie go wyznaczyc jako sasiad, albo zrobic polaczenie z uzyciem spojnej
{
int y = find(x, cleader);
if (neighs[y].find(wyn[el]) == neighs[y].end())
neighs[y][wyn[el]] = el;
else
join(neighs[y][wyn[el]], el, leader, to_join, groups, rep, wyn, done); // jezeli
}
}
}
}
bool alldone = true;
for (int i = 1; i <= k; i++)
if (!done[i])
alldone = false;
if (alldone)
std::cout << "TAK\n";
else
std::cout << "NIE\n";
}
int main()
{
std::ios_base::sync_with_stdio(0);
std::cin.tie(0);
int t = 1;
std::cin >> t;
while (t--)
{
solve();
}
}
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 167 | #include <bits/stdc++.h> #define ll long long #define pi std::pair<int, int> #define pll std::pair<ll, ll> #define vi std::vector<int> #define vll std::vector<ll> #define vpi std::vector<pi> #define vpll std::vector<pll> #define si std::set<int> // no moja logika byla bledna // a ja odkrylem ze umiem czytac ale nie umiem interpretowac // a przynajmniej mam nadzieje ze nie umiem // i zloznosc logarytmiczno liniowa przechodzi // wiec robilbym dsu bez optymalizacji sciezkowej // i laczac sprawdzalbym czy wszystkie miasta naleza do jednego dsu, sa laczne, a wiec beda tworzyc krawedzie // musze jakos rozrozniac laczenie // chce laczyc rozne kolory, gdy sa calkowicie spojne // zas te same kolory powinienem laczyc caly czas // jak sie jakis kolor uspojni to powinienem tez moc polaczyc te same kolory ale nie rozne // no i przesadzilem troszeczke i moj kod nawet nie spelnia zalozen int find(int x, vi &leader) { if (leader[x] == x) return x; return leader[x] = find(leader[x], leader); // zwykly find } void join(int x, int y, vi &leader, std::stack<int> &to_join, vi &groups, std::vector<vi> &rep, vi &wyn, std::vector<bool> &done) { x = find(x, leader); y = find(y, leader); if (x == y) return; if (groups[x] < groups[y]) std::swap(x, y); groups[x] += groups[y]; leader[y] = x; if (groups[x] == rep[wyn[x]].size() && !done[wyn[x]]) { done[wyn[x]] = true; to_join.push(wyn[x]); } } void colorjoin(int x, int y, vi &cleader, std::vector<std::map<int, int>> &neighs, std::vector<bool> &done, std::stack<int> &to_join, vi &groups, std::vector<vi> &rep, vi &wyn, vi &leader) { x = find(x, cleader); y = find(y, cleader); if (x == y) return; if (neighs[x].size() < neighs[y].size()) std::swap(x, y); cleader[y] = x; // o tym tez wypadaloby nie zapominac for (auto &el : neighs[y]) if (!done[el.first]) { if (neighs[x].find(el.first) == neighs[x].end()) // jezeli moge przekopiowac sasiada to to robie neighs[x][el.first] = el.second; else join(neighs[x][el.first], el.second, leader, to_join, groups, rep, wyn, done); // jezeli zas kolory maja sasiadow, o tym samym kolorze, to moga nie byc polaczone a polaczenie jest przez te spojne, co oznacza ze moge polaczyc } } void solve() { int n, m, k; std::cin >> n >> m >> k; std::vector<bool> visited(n + 1), done(k + 1); vi wyn(n + 1), count(k + 1), leader(n + 1), groups(n + 1), cleader(k + 1); std::vector<vi> rep(k + 1), links(n + 1); std::stack<int> to_join; std::vector<std::map<int, int>> neighs(k + 1); for (int i = 1; i <= n; i++) { leader[i] = i; groups[i] = 1; } for (int i = 1; i <= k; i++) cleader[i] = i; for (int i = 1; i <= n; i++) { std::cin >> wyn[i]; rep[wyn[i]].push_back(i); } int a, b; for (int i = 0; i < m; i++) { std::cin >> a >> b; links[a].push_back(b); links[b].push_back(a); if (wyn[a] == wyn[b]) join(a, b, leader, to_join, groups, rep, wyn, done); } for (int i = 1; i <= k; i++) { if (rep[i].size() <= 1) done[i] = true; if (rep[i].size() == 1) to_join.push(i); } while (!to_join.empty()) { int x = to_join.top(); to_join.pop(); for (auto &jel : rep[x]) for (auto &el : links[jel]) { if (wyn[el] != x) { if (done[wyn[el]]) colorjoin(wyn[el], x, cleader, neighs, done, to_join, groups, rep, wyn, leader); // lacze kolory nie kolor z wierzcholkiem else // jezeli sasiad jest niespojny, no to przyda sie go wyznaczyc jako sasiad, albo zrobic polaczenie z uzyciem spojnej { int y = find(x, cleader); if (neighs[y].find(wyn[el]) == neighs[y].end()) neighs[y][wyn[el]] = el; else join(neighs[y][wyn[el]], el, leader, to_join, groups, rep, wyn, done); // jezeli } } } } bool alldone = true; for (int i = 1; i <= k; i++) if (!done[i]) alldone = false; if (alldone) std::cout << "TAK\n"; else std::cout << "NIE\n"; } int main() { std::ios_base::sync_with_stdio(0); std::cin.tie(0); int t = 1; std::cin >> t; while (t--) { solve(); } } |
English