Description
Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the graph are numbered from 1 ton. 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.
Input
The first line of the input contains space-separated two integers — n and m (2 ≤ n ≤ 100, 1 ≤ m ≤ 100), 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, if i ≠ j, (ai, bi, ci) ≠ (aj, bj, cj).
The next line contains a integer — q (1 ≤ q ≤ 100), 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.
Output
For each query, print the answer in a separate line.
Sample Input
Input 4 5 1 2 1 1 2 2 2 3 1 2 3 3 2 4 3 3 1 2 3 4 1 4 Output 2 1 0 Input 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 Output 1 1 1 1 2Hint
Let's consider the first sample.
The figure above shows the first sample. 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.
题意:
给一个n个点,m条边的无向图,每条边有一个颜色color,1<=color<=m,问任意两点之间仅用一种颜色就能连通的道路有几条。
思路:
对边集数组按颜色不降序排序,以颜色种类维护并查集。对每个查询进行并查集的Find操作求和即可。
代码:
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cstdio> using namespace std; struct Edge { int from, to, w; bool operator<(const Edge &a)const{ return w<a.w; } }; struct node { int first, second; }; int n, m; int pre[10010]; Edge edges[110]; node check[110]; void init(){ for(int i=0; i<10010; i++) pre[i] = i; for(int i=0; i<110; i++){ check[i].first = -2; check[i].second = -1; } } int Find(int x){ if(x==pre[x]) return x; else return Find(pre[x]); } bool unite(int x, int y){ x = Find(x); y = Find(y); if(x==y) return false; pre[x] = y; return true; } void sol(int s, int e, int flag){ if(s==-2&&e==-1) return; for(int i=s; i<=e; i++){ bool waste = unite(edges[i].from+flag*n, edges[i].to+flag*n); } return; } int main(){ int cnt, a, b; while(scanf("%d%d", &n, &m)!=EOF){ for(int i=0; i<m; i++){ scanf("%d%d%d", &edges[i].from, &edges[i].to, &edges[i].w); } sort(edges, edges+m); init(); for(int i=0; i<m; i++){ int tmp = check[edges[i].w].first; check[edges[i].w].first = (tmp==-2)?i:tmp; check[edges[i].w].second = i; } for(int i=1; i<=m; i++){ sol(check[i].first, check[i].second, i-1); } scanf("%d", &cnt); for(int i=0; i<cnt; i++){ scanf("%d%d", &a, &b); int ans = 0; for(int j=0; j<m; j++){ int x = Find(a+j*n); int y = Find(b+j*n); if(x==y){ ans++; } } printf("%d\n", ans); } } return 0; }