[2013 ACM/ICPC Asia Regional Nanjing Online C][hdu 4750]Count The Pairs(kruskal + 二分)

http://acm.hdu.edu.cn/showproblem.php?pid=4750

 

题意:

定义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, 0sizeof(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\n", 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 }
View Code 

 

posted @ 2013-09-24 20:11  masterhe  阅读(192)  评论(0编辑  收藏  举报