Mr. Kitayuta has just bought an undirected graph with n vertices and m edges. The vertices of the graph are numbered from 1 to n. Each edge, namely edge i, has a color ci, connecting vertex ai and bi.
Mr. Kitayuta wants you to process the following q queries.
In the i-th query, he gives you two integers - ui and vi.
Find the number of the colors that satisfy the following condition: the edges of that color connect vertex ui and vertex vi directly or indirectly.
The first line of the input contains space-separated two integers - n and m(2 ≤ n ≤ 105, 1 ≤ m ≤ 105), denoting the number of the vertices and the number of the edges, respectively.
The next m lines contain space-separated three integers - ai, bi(1 ≤ ai < bi ≤ n) and ci(1 ≤ ci ≤ m). Note that there can be multiple edges between two vertices. However, there are no multiple edges of the same color between two vertices, that is, ifi ≠ j, (ai, bi, ci) ≠ (aj, bj, cj).
The next line contains a integer- q(1 ≤ q ≤ 105), denoting the number of the queries.
Then follows q lines, containing space-separated two integers - ui and vi(1 ≤ ui, vi ≤ n). It is guaranteed that ui ≠ vi.
For each query, print the answer in a separate line.
4 5 1 2 1 1 2 2 2 3 1 2 3 3 2 4 3 3 1 2 3 4 1 4
2 1 0
5 7 1 5 1 2 5 1 3 5 1 4 5 1 1 2 2 2 3 2 3 4 2 5 1 5 5 1 2 5 1 5 1 4
1 1 1 1 2
Let's consider the first sample.
![](https://i-blog.csdnimg.cn/blog_migrate/02b21f651eb479716de511124a199f52.png)
- Vertex 1 and vertex 2 are connected by color 1 and 2.
- Vertex 3 and vertex 4 are connected by color 3.
- Vertex 1 and vertex 4 are not connected by any single color.
题意是给出了通过不同颜色的边连接的一些点,有Q个查询,查询两个点可以用多少种不同颜色的边连接起来。
如果是一个颜色的边,然后Q个询问,询问两个点是否被连接,可以离线并查集搞。现在是m个颜色的边,那就一个一个颜色并查集搞。
但是,这里还是有问题,就是如何输出结果,这里也学习到了新姿势。就是如果这个颜色的点很多的话,那就遍历Q个查询,记录结果。如果这个颜色的点很少的话,那就O(n^2)记录这些颜色的点。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3fffffff
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int n, m, q;
vector<int>po;
vector<pair<int, int>>edg[maxn];
map<pair<int, int>, int>res;
int fa[maxn], ans[maxn], qu[maxn], qv[maxn], cor[maxn];
int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
fa[x] = y;
}
void input()
{
int i, s, e, cor;
scanf("%d%d", &n, &m);
for (i = 1; i <= m; i++)
{
scanf("%d%d%d", &s, &e, &cor);
edg[cor].push_back(make_pair(s, e));
}
scanf("%d", &q);
for (i = 1; i <= q; i++)
{
scanf("%d%d", &qu[i], &qv[i]);
}
}
void solve()
{
int i, j, k;
for (i = 1; i <= m; i++)
{
int sz = edg[i].size();
if (sz == 0)continue;
po.clear();
for (j = 0; j<sz; j++)
{
po.push_back(edg[i][j].first);
po.push_back(edg[i][j].second);
}
sort(po.begin(), po.end());
po.erase(unique(po.begin(), po.end()), po.end());
int po_sz = po.size();
for (j = 0; j<po_sz; j++)
{
int poin = po[j];
cor[poin] = i;
fa[poin] = poin;
}
for (j = 0; j<sz; j++)
{
int u = edg[i][j].first;
int v = edg[i][j].second;
if (find(u) != find(v))
{
merge(find(u), find(v));
}
}
if ((ll)po_sz*(ll)po_sz > n)
{
for (j = 1; j <= q; j++)
{
if (cor[qu[j]] == i&&cor[qv[j]] == i)
{
if (find(qu[j]) == find(qv[j]))
{
ans[j]++;
}
}
}
}
else
{
for (j = 0; j < po_sz; j++)
{
for (k = j + 1; k < po_sz; k++)
{
if (find(po[j]) == find(po[k]))
{
res[make_pair(po[k], po[j])]++;
res[make_pair(po[j], po[k])]++;
}
}
}
}
}
for (i = 1; i <= q; i++)
{
printf("%d\n", ans[i] + res[make_pair(qu[i], qv[i])]);
}
}
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
input();
solve();
//system("pause");
return 0;
}