JZOJ 4223.旅游

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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值