#include #include #include #include #include #include #include #include int main() { int64_t n, m, q; std::cin >> n >> m >> q; std::vector < std::vector > > edges(n); for (int i = 0; i < m; i++) { int64_t u, v, t; std::cin >> u >> v >> t; edges[u - 1].push_back({ v - 1, t }); edges[v - 1].push_back({ u - 1, t }); } std::vector > queries(q); for (int i = 0; i < q; i++) { int a, b; std::cin >> a >> b; queries[i].first = a - 1; queries[i].second = b - 1; } struct Edge { int v1; int v2; int64_t cost; bool operator<(const Edge& other) const { return cost < other.cost; } }; std::map > queriestohandle; std::vector sortededges; for (int i = 0; i < n; i++) { for (auto it : edges[i]) { if (i < it.first) { sortededges.push_back({ i, it.first, it.second }); queriestohandle[it.second].resize(0); // touch to insert entry } } } std::sort(sortededges.begin(), sortededges.end()); std::vector firstanswers(q); std::vector secondanswers(q); std::vector < std::set > compqueries(n); struct UnionFind { std::vector parent; std::vector compsize; std::vector > queryends; UnionFind(int n) { parent.resize(n); compsize.resize(n); queryends.resize(n); for (int i = 0; i < n; i++) { parent[i] = i; compsize[i] = 1; } } int find(int idx) { if (parent[parent[idx]] != parent[idx]) { parent[idx] = find(parent[idx]); } return parent[idx]; } int size(int idx) { return compsize[find(idx)]; } void doUnion(int idx1, int idx2, std::vector &overlaps) { int f1 = find(idx1); int f2 = find(idx2); if (f1 == f2) return; if (queryends[f1].size() > queryends[f2].size()) { doUnion(idx2, idx1, overlaps); return; } int newsize = compsize[f1] + compsize[f2]; parent[f1] = f2; compsize[f2] = newsize; for (auto it : queryends[f1]) { if (queryends[f2].count(it)) overlaps.push_back(it); else queryends[f2].insert(it); } } }; std::set done; UnionFind uf(n); for (int i = 0; i < q; i++) { uf.queryends[queries[i].first].insert(i); uf.queryends[queries[i].second].insert(i); } for (auto it : sortededges) { if (!done.count(it.cost)) { done.insert(it.cost); for (auto q : queriestohandle[it.cost]) { secondanswers[q] = uf.size(queries[q].first); } } std::vector overlaps; uf.doUnion(it.v1, it.v2, overlaps); for (auto i : overlaps) { firstanswers[i] = it.cost; } auto qit = queriestohandle.find(it.cost); ++qit; if (qit == queriestohandle.end()) { for (auto i : overlaps) secondanswers[i] = n; } else { for (auto i : overlaps) qit->second.push_back(i); } } for (int i = 0; i < q; i++) std::cout << firstanswers[i] << " " << secondanswers[i] << std::endl; }