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
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
Hint
Let's consider 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;
}