xth的旅行——并查集的应用
描述
毕业了,Xth很高兴,因为他要和他的rabbit去双人旅行了。他们来到了水城威尼斯。众所周知(⊙﹏⊙b汗),这里的水路交通很发达,所以xth和rabbit只好坐船穿梭于各个景点之间。但是要知道,rabbit是会晕船的,看到她难受,xth是会心疼的。
已知城市中有n个景点,这些景点之间有m条双向水路,在每条水路上航行时rabbit都会有一个“晕船值”。旅行时,xth会带着rabbit尽量选择晕船值小的路线旅行。但是rabbit也是有一定忍耐限度度的,如果晕船值超过了她的忍耐度,xth会果断决定放弃这条路线。
现在xth想进行若干次询问,给定rabbit的忍耐度,问还有多少对城市(x,y)间会存在可行的旅行路线(如果(x,z)和(z,y)可行,则(x,y)可行,也就是说连通性是可传递的)。
输入格式
第1行三个正整数n、m、Q,分别表示景点数量、水路数量和询问次数。
第2行到第m+1行每行三个正整数x、y、w,表示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<=20,m<=40,Q<=40;
对于40%的数据满足n<=1000,m<=2000,Q<=1000;
对于60%的数据满足n<=3000,m<=6000,Q<=200000;
对于100%的数据满足n<=100000,m<=200000,Q<=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.