现在的位置: 首页 > 综合 > 正文

xth的旅行——并查集的应用

2013年04月18日 ⁄ 综合 ⁄ 共 2742字 ⁄ 字号 评论关闭

描述

毕业了,Xth很高兴,因为他要和他的rabbit去双人旅行了。他们来到了水城威尼斯。众所周知(⊙﹏⊙b汗),这里的水路交通很发达,所以xthrabbit只好坐船穿梭于各个景点之间。但是要知道,rabbit是会晕船的,看到她难受,xth是会心疼的。

已知城市中有n个景点,这些景点之间有m条双向水路,在每条水路上航行时rabbit都会有一个“晕船值”。旅行时,xth会带着rabbit尽量选择晕船值小的路线旅行。但是rabbit也是有一定忍耐限度度的,如果晕船值超过了她的忍耐度,xth会果断决定放弃这条路线。

现在xth想进行若干次询问,给定rabbit的忍耐度,问还有多少对城市(xy)间会存在可行的旅行路线(如果(xz)和(zy)可行,则(xy)可行,也就是说连通性是可传递的)。

输入格式

1行三个正整数nmQ,分别表示景点数量、水路数量和询问次数。

2行到第m+1行每行三个正整数xyw,表示x号景点和y号景点之间有一条晕船值w的双向水路。

m+2行至第m+Q+1行,每行一个正整数k,表示询问中给定的rabbi忍耐度为k

输出格式

Q行,对于每次询问做出回答。

样例输入 Sample Input

5 5 2

1 2 1

2 3 2

3 4 1

4 5 4

5 1 1

1

2

样例输出 Sample Output

4

10

时间限制

各个测试点1s

【样例说明】

第一个询问:(1,2)(1,5)(2,5)(3,4)。其中(2,5)的具体走法为:2-1-5

第二个询问:(1,2)(1,3)(1,4)(1,5)(2,3)(2,4)(2,5)(3,4)(3,5)(4,5)。其中(4,5)的具体走法为:4-3-2-1-5

【数据规模】

对于20%的数据满足n<=20m<=40Q<=40

对于40%的数据满足n<=1000m<=2000Q<=1000

对于60%的数据满足n<=3000m<=6000Q<=200000

对于100%的数据满足n<=100000m<=200000Q<=200000。其他数不超过10^9

【细节提示】

1 给出的n个景点不一定全部互相连通,且两个景点之间可能存在多条道路,也可能存在某条边是从某景点出发回到他自己。

2 对于询问的结果可能很大,请注意使用适当的类型存储。

 

分析:

对于这道题来说,处理询问的顺序先后其实是没有关系的

所以,可以对询问先读入排序,再按从小到大的顺序挨个求解,

这样的话,求解一遍即可。

具体点的,连接两个联通块时,要使用并查集,

把两个联通块相连,具体的并查集过程不再赘述。

并查集过程中要用到一个sum[x]数组,

记录以x为根的联通块总共的存在的道路。

并查集中“并”的时候,

sum[x]:=sum[x]*sum[y]

y的父节点改为x。

  1 program trip;
2 var
3 i,j,n,m,k,l,q,n1,n2,f1,f2:longint;
4 ans:int64;
5 a,w,s,e,c,fa,sum:array[0..200000]of longint;
6 f:array[0..200000]of int64;
7
8 procedure sort(l,r:longint);
9 var
10 i,j,x,y:longint;
11 begin
12 i:=l;j:=r;
13 x:=c[(l+r)div 2];
14 repeat
15 while c[i]<x do inc(i);
16 while c[j]>x do dec(j);
17 if i<=j then
18 begin
19 y:=c[i];c[i]:=c[j];c[j]:=y;
20 y:=s[i];s[i]:=s[j];s[j]:=y;
21 y:=e[i];e[i]:=e[j];e[j]:=y;
22 inc(i);dec(j);
23 end;
24 until i>j;
25 if l<j then sort(l,j);
26 if i<r then sort(i,r);
27 end;
28
29 procedure qsort(l,r:longint);
30 var
31 i,j,x,y:longint;
32 begin
33 i:=l;j:=r;
34 x:=a[(l+r)div 2];
35 repeat
36 while a[i]<x do inc(i);
37 while a[j]>x do dec(j);
38 if i<=j then
39 begin
40 y:=a[i];a[i]:=a[j];a[j]:=y;
41 y:=w[i];w[i]:=w[j];w[j]:=y;
42 inc(i);dec(j);
43 end;
44 until i>j;
45 if l<j then qsort(l,j);
46 if i<r then qsort(i,r);
47 end;//两遍快排不解释
48
49 function getfa(x:longint):longint;
50 var
51 i,j:longint;
52 begin
53 j:=fa[x];
54 if fa[j]<>j then fa[x]:=getfa(j);
55 exit(fa[x]);
56 end;//并查集的查(有路径压缩)
57
58 procedure union(x,y:longint);
59 var
60 i,j:longint;
61 begin
62 fa[y]:=x;
63 end;//并查集的并
64
65 begin
66 assign(input,'trip.in');
67 reset(input);
68 assign(output,'trip.out');
69 rewrite(output);
70 readln(n,m,q);
71 for i:=1 to m do
72 readln(s[i],e[i],c[i]);
73 sort(1,m);
74 for i:=1 to q do
75 begin
76 readln(a[i]);
77 w[i]:=i;
78 end;
79 qsort(1,q);
80 for i:=1 to n do fa[i]:=i;
81 for i:=1 to n do sum[i]:=1;
82 n2:=1;
83 n1:=0;//预处理
84 for i:=1 to q do
85 begin
86 while (n2<=m)and(c[n2]<=a[i]) do
87 begin
88 f1:=getfa(s[n2]);
89 f2:=getfa(e[n2]);
90 if f1<>f2 then
91 begin
92 union(f1,f2);
93 ans:=ans+sum[f1]*sum[f2];
94 sum[f1]:=sum[f1]+sum[f2];
95 end;
96 inc(n2);
97 end;
98 f[w[i]]:=ans;
99 end;//按顺序处理并输出
100 for i:=1 to q do writeln(f[i]);
101 close(input);
102 close(output);
103 end.

抱歉!评论已关闭.