#include <bits/stdc++.h>
using namespace std;
class DSU {
private:
vector<int> parent;
vector<int> sizes;
public:
DSU(int n) : parent(n), sizes(n, 1) {
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
int find(int i) {
if (i == parent[i]) return i;
return parent[i] = find(parent[i]);
}
void merge(int u, int v) {
int ultimateParentU = find(u);
int ultimateParentV = find(v);
if (ultimateParentU == ultimateParentV) return;
if (sizes[ultimateParentU] < sizes[ultimateParentV]) {
parent[ultimateParentU] = ultimateParentV;
sizes[ultimateParentV] += sizes[ultimateParentU];
} else {
parent[ultimateParentV] = ultimateParentU;
sizes[ultimateParentU] += sizes[ultimateParentV];
}
}
};
vector<string> reduceQueries(vector<vector<string>>& synonyms, vector<string>& queries) {
unordered_set<string> set;
unordered_map<string, int> map;
unordered_map<int, string> reverseMap;
int count = 0;
for (const auto& s : synonyms) {
set.insert(s[0]);
set.insert(s[1]);
if (!map.count(s[0])) {
map[s[0]] = count;
reverseMap[count] = s[0];
count++;
}
if (!map.count(s[1])) {
map[s[1]] = count;
reverseMap[count] = s[1];
count++;
}
}
int n = set.size();
DSU dsu(n);
for (const auto& s : synonyms) {
dsu.merge(map[s[0]], map[s[1]]);
}
unordered_map<string, string> mapper;
unordered_map<string, int> uniques;
for (const auto& s : queries) {
vector<string> splitted;
string word;
for (char c : s) {
if (c == ' ') {
splitted.push_back(word);
word.clear();
} else {
word += c;
}
}
splitted.push_back(word);
string u = splitted[0];
string v = splitted[1];
int parentU = dsu.find(map[u]);
int parentV = dsu.find(map[v]);
string first = reverseMap[parentU];
string second = reverseMap[parentV];
string newQuery = first + " " + second;
mapper[s] = newQuery;
uniques[newQuery] = 1;
}
vector<string> answer;
for (const auto& s : queries) {
if (uniques.count(mapper[s])) {
answer.push_back(s);
uniques[mapper[s]]--;
if (uniques[mapper[s]] == 0) {
uniques.erase(mapper[s]);
}
}
}
return answer;
}
int main() {
vector<vector<string>> synonyms = {{"get", "bring"}, {"water", "liquid"}, {"bring", "nothing"}};
vector<string> queries = {"get water", "bring water", "get liquid", "bring get"};
vector<string> reducedQueries = reduceQueries(synonyms, queries);
cout << "Reduced Queries:";
for (const auto& query : reducedQueries) {
cout << " " << query;
}
cout << endl;
return 0;
}