Description
在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci。
Byteasar作为Byteland 公路建设项目的总工程师,他决定选定一个区间[l, r],仅使用编号在该区间内的道路。他希望选择一些道路去修建,使得连通块的个数尽量少,同时,他不喜欢修建多余的道路,因此每个连通块都可以看成一棵树的结构。
为了选出最佳的区间,Byteasar 会不断选择q 个区间,请写一个程序,帮助Byteasar 计算每个区间内修建公路的最小总费用。
Input
第一行包含三个正整数n, m, q,表示城市数、道路数和询问数。
接下来m 行,每行三个正整数ui,vi,ci,表示一条连接城市ui 和vi 的双向道路,费用为ci。
接下来q 行,每行两个正整数li, ri,表示一个询问。
Output
输出q 行,每行一个整数,即最小总费用。
Sample Input
3 5 2
1 3 2
2 3 1
2 1 6
3 1 7
2 3 7
2 5
3 4
Sample Output
7
13
Data Constraint
题解
这是一道十分套路的题啊
注意到n的值十分小,而且给的空间有点大,所以我们考虑直接用线段树强行储存信息,具体就是对于一个边的区间我们维护所有有用的点,合并的时候世界做一次克鲁斯卡尔就好了
贴代码
var
tree:array[0..300005,0..105]of longint;
a:array[0..100005,1..3]of longint;
fa:array[0..100005]of longint;
b,c:array[0..105]of longint;
d:array[0..205]of longint;
i,j,k,l,m,n,q,x,y,ans,t1,t2:longint;
function getfather(x:longint):longint;
begin
if fa[x]=x then exit(x) else fa[x]:=getfather(fa[x]);
exit(fa[x]);
end;
procedure change(v,l,r,x:longint);
var
mid:longint;
begin
if l=r then
begin
tree[v,0]:=1;
tree[v,1]:=x;
end else
begin
mid:=(l+r) div 2;
if x<=mid then change(v*2,l,mid,x) else change(v*2+1,mid+1,r,x);
end;
end;
procedure bing;
var
i,j,k:longint;
begin
j:=1; k:=1; i:=1;
while (j<=t1) and (k<=t2) do
if a[b[j],3]<a[c[k],3] then
begin
d[i]:=b[j];
inc(i);
inc(j);
end else
begin
d[i]:=c[k];
inc(i);
inc(k);
end;
if j<=t1 then
while j<=t1 do
begin
d[i]:=b[j];
inc(j);
inc(i);
end;
if k<=t2 then
while k<=t2 do
begin
d[i]:=c[k];
inc(k);
inc(i);
end;
d[0]:=i-1;
end;
procedure maketree(v,l,r:longint);
var
i,j,k,mid:longint;
begin
if l=r then exit;
mid:=(l+r) div 2;
maketree(v*2,l,mid);
maketree(v*2+1,mid+1,r);
for i:=1 to tree[v*2,0] do b[i]:=tree[v*2,i];
for i:=1 to tree[v*2+1,0] do c[i]:=tree[v*2+1,i];
t1:=tree[v*2,0]; t2:=tree[v*2+1,0];
bing;
for i:=1 to n do fa[i]:=i;
k:=0;
for i:=1 to d[0] do
begin
x:=getfather(a[d[i],1]);
y:=getfather(a[d[i],2]);
if x<>y then
begin
inc(k);
fa[x]:=y;
tree[v,k]:=d[i];
if k=n-1 then break;
end;
end;
tree[v,0]:=k;
end;
procedure get(v,l,r,x,y:longint);
var
i,mid:longint;
begin
if (l=x) and (r=y) then
begin
c:=tree[v];
bing;
for i:=1 to n do fa[i]:=i;
k:=0;
for i:=1 to d[0] do
begin
x:=getfather(a[d[i],1]);
y:=getfather(a[d[i],2]);
if x<>y then
begin
inc(k);
fa[x]:=y;
b[k]:=d[i];
if k=n-1 then break;
end;
end;
b[0]:=k;
end else
begin
mid:=(l+r) div 2;
if y<=mid then get(v*2,l,mid,x,y) else
if x>mid then get(v*2+1,mid+1,r,x,y) else
begin
get(v*2,l,mid,x,mid);
get(v*2+1,mid+1,r,mid+1,y);
end;
end;
end;
begin
assign(input,'highway.in'); reset(input);
assign(output,'highway.out'); rewrite(output);
readln(n,m,q);
for i:=1 to m do
begin
readln(a[i,1],a[i,2],a[i,3]);
change(1,1,m,i);
end;
maketree(1,1,m);
for i:=1 to q do
begin
readln(x,y);
ans:=0;
fillchar(b,sizeof(b),0);
get(1,1,m,x,y);
for j:=1 to b[0] do ans:=ans+a[b[j],3];
writeln(ans);
end;
close(input); close(output);
end.