10 10 10
7 2 1
6 8 3
4 5 8
5 8 2
2 8 9
6 4 5
2 1 5
8 10 5
7 3 7
7 8 8
10 //查询长度
6
1
5
9
1
8
2
7
6
7 2 1
6 8 3
4 5 8
5 8 2
2 8 9
6 4 5
2 1 5
8 10 5
7 3 7
7 8 8
10 //查询长度
6
1
5
9
1
8
2
7
6
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int M = 10005;
/*
本题题意有必要说一下, 给出一系列查询长度, 要求你找出任意两点间的最长边小于等于给出的查询
长度, 做法是对给出的边排序,具体看代码, 我也是看了别人写的才明白题意的。
*/
struct node {
int x;
int y;
int d;
}edge[M*5];
struct Node {
int len;
int ans;
int id;
}query[M];
int p[M];
int sum[M];
int n, m, q;
bool cmp(node p1, node p2) {
return p1.d < p2.d;
}
bool cmp1(Node p1, Node p2) {
return p1.len < p2.len;
}
bool cmp2(Node p1, Node p2) {
return p1.id < p2.id;
}
void init() {
for(int i = 1; i <= n; i++) {
p[i] = i;
sum[i] = 1;
}
}
int Find(int a) {
return a == p[a] ? a : p[a] = Find(p[a]);
}
int Union(int a, int b) {
a = Find(a);
b = Find(b);
if(a == b)
return 0;
else {
p[a] = b;
int temp = sum[a]*sum[b];
sum[b] += sum[a];
return temp;
}
}
int main()
{
while(scanf("%d%d%d", &n, &m, &q) != EOF) {
init();
for(int i = 0; i < m; i++) {
scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].d);
}
for(int i = 0; i < q; i++) {
scanf("%d", &query[i].len);
query[i].id = i;
query[i].ans = 0;
}
sort(edge, edge+ m, cmp);
sort(query, query+q, cmp1);
int cnt = 0;
for(int i = 0; i < q; i++) {
while(edge[cnt].d <= query[i].len && cnt < m) {
query[i].ans += Union(edge[cnt].x, edge[cnt].y);
cnt++;
}
if(i > 0)
query[i].ans += query[i-1].ans;
}
sort(query, query+q, cmp2);
for(int i = 0; i < q; i++) {
printf("%d\n", query[i].ans);
}
}
return 0;
}