题意:
定义f(u,v)为u到v每条路径上的最大边的最小值..现在有一些询问..问f(u,v)>=t的点对有所少对,注意(1,2)和(2,1)是不同的点对
分析:
原来最小生成树有一个很鬼畜的结论,那就是一个图的最小生成树中任意两个点的路径中的最大边一定最小。(妈蛋,完全不知道这个)
然后此题就变得很明朗了,用kruskal算法,加边的时候此边连接的两个集合的路径中的最大边就是这个边,存储下来,询问的时候二分查找即可。
1 #pragma comment(linker, "/STACK:102400000,102400000")
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 typedef long long ll;
6 struct Edge {
7 int u, v, len;
8 };
9 const int N = 10000 + 3;
10 const int E = 500000 + 3;
11
12 int fa[N], cnt[N];
13
14 Edge eg[E];
15 int idx, id[E];
16
17 int n, m;
18 ll ans[E];
19
20 int Find(int x) {
21 if (fa[x] != x) fa[x] = Find(fa[x]);
22 return fa[x];
23 }
24 bool cmp(const Edge& a, const Edge& b) {
25 return a.len < b.len;
26 }
27 void work() {
28 for (int i = 1; i <= n; ++i)
29 fa[i] = i, cnt[i] = 1;
30
31 id[0] = -1;
32 for (int i = 0; i < m; ++i) {
33 scanf("%d%d%d", &eg[i].u, &eg[i].v, &eg[i].len);
34 ++eg[i].u, ++eg[i].v;
35 id[i + 1] = eg[i].len;
36 }
37
38 std::sort(id, id + m + 1);
39 for (int i = 0; i < m; ++i)
40 eg[i].len = std::lower_bound(id, id + m + 1, eg[i].len) - id;
41
42 memset(ans, 0, sizeof(ans));
43
44 std::sort(eg, eg + m, cmp);
45 int x, y;
46 for (int i = 0; i < m; ++i) {
47 x = Find(eg[i].u), y = Find(eg[i].v);
48 if (x != y) {
49 ans[eg[i].len] = ans[eg[i].len] + cnt[x] * cnt[y];
50 cnt[x] += cnt[y];
51 fa[y] = x;
52 }
53 }
54
55 for (int i = m; i >= 0; --i)
56 ans[i] = ans[i] + ans[i + 1];
57
58 int Q, l, r, mid;
59 scanf("%d", &Q);
60 while (Q -- > 0) {
61 scanf("%d", &x);
62 l = -1, r = m + 1;
63 while (r - l > 1) {
64 mid = (l + r) >> 1;
65 if (id[mid] >= x)
66 r = mid;
67 else
68 l = mid;
69 }
70 printf("%lld ", ans[r] * 2);
71 }
72 }
73 int main() {
74 // freopen("a.in", "r", stdin);
75 while (2 == scanf("%d%d", &n, &m)) {
76 work();
77 }
78 return 0;
79 }
2 #include <cstdio>
3 #include <algorithm>
4 #include <cstring>
5 typedef long long ll;
6 struct Edge {
7 int u, v, len;
8 };
9 const int N = 10000 + 3;
10 const int E = 500000 + 3;
11
12 int fa[N], cnt[N];
13
14 Edge eg[E];
15 int idx, id[E];
16
17 int n, m;
18 ll ans[E];
19
20 int Find(int x) {
21 if (fa[x] != x) fa[x] = Find(fa[x]);
22 return fa[x];
23 }
24 bool cmp(const Edge& a, const Edge& b) {
25 return a.len < b.len;
26 }
27 void work() {
28 for (int i = 1; i <= n; ++i)
29 fa[i] = i, cnt[i] = 1;
30
31 id[0] = -1;
32 for (int i = 0; i < m; ++i) {
33 scanf("%d%d%d", &eg[i].u, &eg[i].v, &eg[i].len);
34 ++eg[i].u, ++eg[i].v;
35 id[i + 1] = eg[i].len;
36 }
37
38 std::sort(id, id + m + 1);
39 for (int i = 0; i < m; ++i)
40 eg[i].len = std::lower_bound(id, id + m + 1, eg[i].len) - id;
41
42 memset(ans, 0, sizeof(ans));
43
44 std::sort(eg, eg + m, cmp);
45 int x, y;
46 for (int i = 0; i < m; ++i) {
47 x = Find(eg[i].u), y = Find(eg[i].v);
48 if (x != y) {
49 ans[eg[i].len] = ans[eg[i].len] + cnt[x] * cnt[y];
50 cnt[x] += cnt[y];
51 fa[y] = x;
52 }
53 }
54
55 for (int i = m; i >= 0; --i)
56 ans[i] = ans[i] + ans[i + 1];
57
58 int Q, l, r, mid;
59 scanf("%d", &Q);
60 while (Q -- > 0) {
61 scanf("%d", &x);
62 l = -1, r = m + 1;
63 while (r - l > 1) {
64 mid = (l + r) >> 1;
65 if (id[mid] >= x)
66 r = mid;
67 else
68 l = mid;
69 }
70 printf("%lld ", ans[r] * 2);
71 }
72 }
73 int main() {
74 // freopen("a.in", "r", stdin);
75 while (2 == scanf("%d%d", &n, &m)) {
76 work();
77 }
78 return 0;
79 }