您的位置:首页 > 其它

【省选专题一】图论 jzoj 5060.【GDOI2017第二轮模拟day1】公路建设 线段树+最小生成树+并查集

2018-01-07 17:21 621 查看
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



分析:我们建一棵线段树维护[l,r]的答案,显然对于一个段,最多有n-1条边,我们可以使用归并合并两个区间(两个区间都是有序的,这个用归并可以做出来,然后按从小到大插入边,做最小生成树)。空间大得可以,时间也是卡过= =

代码:

type
node=record
x,y,w:longint;
end;
arr=array [1..102] of node;
var
n,m,test,x,y,numa,sum,i,j:longint;
tree:array [1..300001] of arr;
num:array [1..300001] of longint;
a:array [1..100001] of node;
p:array [1..101] of longint;
ans,b:arr;

function find(x:longint):longint;
var root,w,y:longint;
begin
y:=x;
while p[y]>0 do y:=p[y];
root:=y;
y:=x;
while p[y]>0 do
begin
w:=p[y];
p[y]:=root;
y:=w;
end;
exit(root);
end;

procedure union(x,y:longint);
var u,v:longint;
begin
u:=find(x);
v:=find(y);
if u<>v then p[v]:=u;
end;

procedure merge(x:arr;numx:longint; var y:arr; var numy:longint);
var i,j,c:longint;
begin
for i:=1 to n do
p[i]:=0;
i:=1; j:=1; c:=0;
while (i<=numx) or (j<=numy) do
begin
while (i<=numx) and (find(x[i].x)=find(x[i].y)) do inc(i);
while (j<=numy) and (find(y[j].x)=find(y[j].y)) do inc(j);
if (i>numx) and (j>numy) then break;
if ((j>numy) or (x[i].w<y[j].w)) and (i<=numx) then
begin
inc(c);
b[c]:=x[i];
union(x[i].x,x[i].y);
inc(i);
end
else
begin
inc(c);
b[c]:=y[j];
union(y[j].x,y[j].y);
inc(j);
end;
if c>=n-1 then break;
end;
numy:=c;
for i:=1 to c do
y[i]:=b[i];
end;

procedure build_tree(p,l,r:longint);
var mid:longint;
begin
if (l=r) then
begin
num[p]:=1;
tree[p,1]:=a[l];
exit;
end;
mid:=(l+r) shr 1;
build_tree(p*2,l,mid);
build_tree(p*2+1,mid+1,r);
tree[p]:=tree[p*2];
num[p]:=num[p*2];
merge(tree[p*2+1],num[p*2+1],tree[p],num[p]);
end;

procedure count(p,l,r,s,t:longint);
var mid:longint;
begin
if (l=s) and (r=t) then
begin
merge(tree[p],num[p],ans,numa);
exit;
end;
mid:=(l+r) shr 1;
if t<=mid then count(p*2,l,mid,s,t)
else
if s>=mid+1 then count(p*2+1,mid+1,r,s,t)
else
begin
count(p*2,l,mid,s,mid);
count(p*2+1,mid+1,r,mid+1,t);
end;
end;

begin
assign(input,'highway.in');
assign(output,'highway.out');
reset(input);
rewrite(output);
readln(n,m,test);
for i:=1 to m do
readln(a[i].x,a[i].y,a[i].w);
build_tree(1,1,m);
for i:=1 to test do
begin
readln(x,y);
numa:=0;
fillchar(ans,sizeof(ans),0);
count(1,1,m,x,y);
sum:=0;
for j:=1 to numa do
sum:=sum+ans[j].w;
writeln(sum);
end;
close(input);
close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: