Description
给你一个n个点,m条边的图,每条边有一个权值d,设有两点a,b,从a到b中的路径权值最大值不能超过x。求满足条件的(a,b)的对数。
Input
第一行一个数test,表示有test组数据。
对于每组数据,第一行有三个数n,m,q,q表示有q个询问。
接下来m行,每行三个数x,y,d,表示有一条连接x,y(双向),权值为d的道路。
最后q行,每行一个询问x。
Output
对于每组数据,你需要输出q行,依次回答所有询问。
Sample Input
1
5 5 3
2 3 6334
1 5 15724
3 5 5705
4 3 12382
1 3 21726
6000
10000
13000
Sample Output
2
6
12
Data Constraint
test不会很大。
对于前10%的数据,n≤200
对于前40%的数据,n≤500,m≤2000,q≤100,d≤1000.
对于100%的数据,q≤5000,n≤20000,m≤100000,d≤100000.
Solution
这是一个联通图,所以我们按照d排序,按x排序。我们用并查集维护两个连通块的联通性。将询问混入边中排序即可。
Code
type arr=array[0..200001,1..3] of longint;
var f,g,ans:array[0..200001] of longint;
q,c:arr;
i,j,k,l,n,m,t,s,x,y,_,p:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure qsort(l,r,p:longint;var c:arr);
var i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=c[(l+r) div 2,p];
repeat
while c[i,p]<mid do inc(i);
while c[j,p]>mid do dec(j);
if i<=j then
begin
c[0]:=c[i];
c[i]:=c[j];
c[j]:=c[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j,p,c);
if i<r then qsort(i,r,p,c);
end;
function get(n:longint):longint;
begin
if f[n]=0 then exit(n)
else
begin
f[n]:=get(f[n]);
exit(f[n]);
end;
end;
begin
readln(_);
while _>0 do
begin
fillchar(f,sizeof(f),0);
fillchar(ans,sizeof(ans),0);
dec(_);
readln(n,m,k);
for i:=1 to n do g[i]:=1;
for i:=1 to m do read(c[i,1],c[i,2],c[i,3]);
qsort(1,m,3,c);
for i:=1 to k do
begin
readln(q[i,1]);
q[i,2]:=i;
end;
qsort(1,k,1,q);
t:=0;
j:=1;
for i:=1 to k do
begin
while (j<m)and(c[j,3]<=q[i,1]) do
begin
x:=get(c[j,1]);
y:=get(c[j,2]);
if x<>y then
begin
f[y]:=x;
t:=t+g[x]*g[y]*2;
g[x]:=g[x]+g[y];
g[y]:=0;
end;
inc(j);
end;
ans[q[i,2]]:=t;
end;
for i:=1 to k do writeln(ans[i]);
end;
end.
——2016.2.16