#include <bits/stdc++.h>
using namespace std;
struct JoinData {
int rep;
int rank = 0;
int size = 1;
};
void join(JoinData reps[], int a, int b) {
if(a == b) return;
if(reps[a].rank <= reps[b].rank) {
reps[a].rep = b;
reps[b].size += reps[a].size;
} else {
reps[b].rep = a;
reps[a].size += reps[b].size;
}
if(reps[a].rank == reps[b].rank) reps[b].rank++;
return;
}
int find(JoinData reps[], int x) {
if(reps[x].rep != reps[reps[x].rep].rep) {
reps[x].rep = find(reps, reps[x].rep);
}
return reps[x].rep;
}
int main() {
cin.tie(nullptr); ios_base::sync_with_stdio(false);
int num; cin >> num;
while(num--) {
int wierzcholki, polaczenia, grupy;
cin >> wierzcholki >> polaczenia >> grupy;
vector<int> grupa(wierzcholki);
vector<unordered_set<int>> groups(grupy);
JoinData reps[wierzcholki];
queue<int> removalQueue;
for(int i = 0; i < wierzcholki; i++) {
cin >> grupa[i]; grupa[i]--;
groups[grupa[i]].insert(i);
reps[i].rep = i;
}
for(int i = 0; i < grupy; i++) {
if(groups[i].size() <= 1) {
removalQueue.push(i);
}
}
vector<vector<int>> G(wierzcholki);
int a, b;
for(int i = 0; i < polaczenia; i++) {
cin >> a >> b;
G[a-1].push_back(b-1);
G[b-1].push_back(a-1);
}
// Scan the whole graph, merging any two groups of the same vertices that touch
// While there are groups that hit their maximums:
// - Remove the group from consideration
// - Scan the entire group's vertices, and merge any two that share the connection, but we not connected yet
// If all vertices can be removed, then TAK
// If not, then NIE
int x, y;
int sum;
for(int i = 0; i < wierzcholki; i++) {
for(int j = 0; j < G[i].size(); j++) {
if(grupa[i] == grupa[G[i][j]]) {
x = find(reps, i);
y = find(reps, G[i][j]);
if(x != y) {
sum = reps[x].size + reps[y].size;
join(reps, x, y);
if(sum == groups[grupa[i]].size()) {
removalQueue.push(grupa[i]);
}
}
}
}
}
int usunieteGrupy = 0;
int usuwanaGrupa, firstElem;
vector<unordered_set<int>> conn(grupy);
while(!removalQueue.empty()) {
usunieteGrupy++;
usuwanaGrupa = removalQueue.front(); removalQueue.pop();
for(auto &u : groups[usuwanaGrupa]) {
for(auto &v : G[u]) {
conn[grupa[v]].insert(v);
}
}
firstElem = -1;
for(int i = 0; i < grupy; i++) {
if(i == usuwanaGrupa) continue;
if(!conn[i].empty()) {
firstElem = *conn[i].begin();
conn[i].erase(conn[i].begin());
for(auto &u : conn[i]) {
x = find(reps, u);
y = find(reps, firstElem);
if(x != y) {
sum = reps[x].size + reps[y].size;
join(reps, x, y);
if(sum == groups[grupa[x]].size()) {
removalQueue.push(grupa[x]);
}
}
}
conn[i].clear();
}
}
if(!groups[usuwanaGrupa].empty() && firstElem != -1) {
join(reps, find(reps, *(groups[usuwanaGrupa].begin())), find(reps, firstElem));
for(auto &d : groups[usuwanaGrupa]) {
grupa[d] = grupa[firstElem];
groups[grupa[firstElem]].insert(d);
}
groups[usuwanaGrupa].clear();
}
}
if(usunieteGrupy == grupy) {
cout << "TAK\n";
} else {
cout << "NIE\n";
}
}
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 | #include <bits/stdc++.h> using namespace std; struct JoinData { int rep; int rank = 0; int size = 1; }; void join(JoinData reps[], int a, int b) { if(a == b) return; if(reps[a].rank <= reps[b].rank) { reps[a].rep = b; reps[b].size += reps[a].size; } else { reps[b].rep = a; reps[a].size += reps[b].size; } if(reps[a].rank == reps[b].rank) reps[b].rank++; return; } int find(JoinData reps[], int x) { if(reps[x].rep != reps[reps[x].rep].rep) { reps[x].rep = find(reps, reps[x].rep); } return reps[x].rep; } int main() { cin.tie(nullptr); ios_base::sync_with_stdio(false); int num; cin >> num; while(num--) { int wierzcholki, polaczenia, grupy; cin >> wierzcholki >> polaczenia >> grupy; vector<int> grupa(wierzcholki); vector<unordered_set<int>> groups(grupy); JoinData reps[wierzcholki]; queue<int> removalQueue; for(int i = 0; i < wierzcholki; i++) { cin >> grupa[i]; grupa[i]--; groups[grupa[i]].insert(i); reps[i].rep = i; } for(int i = 0; i < grupy; i++) { if(groups[i].size() <= 1) { removalQueue.push(i); } } vector<vector<int>> G(wierzcholki); int a, b; for(int i = 0; i < polaczenia; i++) { cin >> a >> b; G[a-1].push_back(b-1); G[b-1].push_back(a-1); } // Scan the whole graph, merging any two groups of the same vertices that touch // While there are groups that hit their maximums: // - Remove the group from consideration // - Scan the entire group's vertices, and merge any two that share the connection, but we not connected yet // If all vertices can be removed, then TAK // If not, then NIE int x, y; int sum; for(int i = 0; i < wierzcholki; i++) { for(int j = 0; j < G[i].size(); j++) { if(grupa[i] == grupa[G[i][j]]) { x = find(reps, i); y = find(reps, G[i][j]); if(x != y) { sum = reps[x].size + reps[y].size; join(reps, x, y); if(sum == groups[grupa[i]].size()) { removalQueue.push(grupa[i]); } } } } } int usunieteGrupy = 0; int usuwanaGrupa, firstElem; vector<unordered_set<int>> conn(grupy); while(!removalQueue.empty()) { usunieteGrupy++; usuwanaGrupa = removalQueue.front(); removalQueue.pop(); for(auto &u : groups[usuwanaGrupa]) { for(auto &v : G[u]) { conn[grupa[v]].insert(v); } } firstElem = -1; for(int i = 0; i < grupy; i++) { if(i == usuwanaGrupa) continue; if(!conn[i].empty()) { firstElem = *conn[i].begin(); conn[i].erase(conn[i].begin()); for(auto &u : conn[i]) { x = find(reps, u); y = find(reps, firstElem); if(x != y) { sum = reps[x].size + reps[y].size; join(reps, x, y); if(sum == groups[grupa[x]].size()) { removalQueue.push(grupa[x]); } } } conn[i].clear(); } } if(!groups[usuwanaGrupa].empty() && firstElem != -1) { join(reps, find(reps, *(groups[usuwanaGrupa].begin())), find(reps, firstElem)); for(auto &d : groups[usuwanaGrupa]) { grupa[d] = grupa[firstElem]; groups[grupa[firstElem]].insert(d); } groups[usuwanaGrupa].clear(); } } if(usunieteGrupy == grupy) { cout << "TAK\n"; } else { cout << "NIE\n"; } } return 0; } |
English