题目大意:给出一个定义,如果一个块为连通块,且连通块里面的任意两点的长度大于外界的点到该块的点的长度,那这个块就称KTO
现在问KTO里面的点的数量有多少
解题思路:kruscal算法,边从大到小排,暴力就可以过,别看那么多条边,其实数据并不是很大
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 5010
#define M 12500010
#define INF 0x3f3f3f3f
struct Edge{
int u, v, c;
}E[M];
int n, m;
int num[N], f[N];
int cmp(const Edge &a, const Edge &b) {
return a.c > b.c;
}
void init() {
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++)
scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].c);
for (int i = 1; i <= n; i++) {
f[i] = i;
num[i] = 1;
}
}
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
void solve() {
sort(E, E + m, cmp);
int fx, fy;
int cnt = n, ans = 0;
for (int i = 0; i < m; i++) {
fx = find(E[i].u);
fy = find(E[i].v);
if (fx != fy) {
f[fy] = fx;
num[fx] += num[fy];
int Min = INF, Max = -INF;
for (int j = 0; j < m; j++) {
int xx = find(E[j].u);
int yy = find(E[j].v);
if (xx == yy && xx == fx)
Min = min(Min, E[j].c);
else if(xx == fx || yy == fx)
Max = max(Max, E[j].c);
}
if (Min > Max)
ans += num[fx];
}
}
printf("%d\n", ans);
}
int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}