HDU 5441 离线处理 + 并查集

题意:给n个节点m条带权值边的无向图。然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通;2)其路径的最大权值不能超过询问值。

分析:如果没次询问一次,dfs一次,很可能超时,因此可以用并查集。离线处理,把边按权值排序,把问题按大小排序。然后离线的过程就是不断向图中加边的过程。

比如样例如下:

然后离线处理,排完序后将会是一条一条的加边:问题也排了序,因此是个累加过程。。。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <sstream>
 4 #include <cmath>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <string>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <queue>
12 #include <stack>
13 #include <algorithm>
14 #define ll long long
15 #define mem(m, a) memset(m, a, sizeof(m))
16 #define repu(i, a, b) for(int i = a; i < b; i++)
17 #define maxn 100005
18 const double PI=-acos(-1.0);
19 using namespace std;
20 struct node
21 {
22     int x,y,z;
23     bool operator < (const node &a) const
24     {
25         return z < a.z;
26     }
27 } e[maxn];
28 struct Q
29 {
30     int w,id;
31     bool operator < (const Q &a) const
32     {
33         return w < a.w;
34     }
35 } q[maxn];
36 int ans[maxn];
37 int fa[maxn],num[maxn];
38 int find_set(int x)
39 {
40     if(x==fa[x])
41         return fa[x];
42     else
43         return fa[x]=find_set(fa[x]);
44 }
45 int main()
46 {
47     int n,m,k,t;
48     scanf("%d",&t);
49     while(t--)
50     {
51         scanf("%d%d%d",&n,&m,&k);
52         repu(i,0,m)
53         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
54         repu(i,0,k)
55         scanf("%d",&q[i].w),q[i].id=i;
56         sort(e,e+m);
57         sort(q,q+k);
58         repu(i,1,1+n)
59         fa[i]=i,num[i]=1;
60         int cnt=0,j=0;
61         repu(i,0,k)
62         {
63             while(j<m&&e[j].z<=q[i].w)
64             {
65                 int x=find_set(e[j].x);
66                 int y=find_set(e[j].y);///找各自的所属的集合编号
67                 if(x != y)
68                 {
69                     cnt += num[x]*num[y];///各自集合的数目相乘
70                     fa[x] = y;///因为已经统一集合了
71                     num[y] += num[x];///y集合的数目就可以直接加上x的数目
72                 }
73                 j++;
74             }
75             ans[q[i].id] = 2*cnt;
76         }
77         repu(i,0,k)
78         printf("%d\n",ans[i]);
79     }
80     return 0;
81 }
View Code

 

posted @ 2015-09-14 23:32  一麻袋码的玛侬  阅读(426)  评论(0编辑  收藏  举报