zoukankan      html  css  js  c++  java
  • jzoj2940. 生成输入数据

    Description

    首先看到题目别太开心,这题可不是让你出数据~^_*
    背景神马的就忽略了。这题就是给你一棵带边权的树,然后这棵树是某个完全图唯一的最小生成树。问原来的完全图中所有边可能的最小边权和是多少。
    完全图是任意两个点之间都有边相连的图。

    Input

    第一行包含一个整数T表示数据组数。
    每组数据第一行一个整数N表示点数。
    接下来N-1行每行三个整数ai,bi,wi表示最小生成树上ai和bi之间有一条权值为wi的边。

    Output

    输出应有T行,每行表示一组数据的答案。

    Sample Input

    2
    3
    1 2 4
    2 3 7
    4
    1 2 1
    1 3 1
    1 4 2

    Sample Output

    19
    12

    Data Constraint

    20%的数据满足:T≤5,n≤5,wi≤5
    另外30%的数据满足:n≤1000,给定的树是一条链
    100%的数据满足:T≤10,n≤20000,wi≤10000

    题解

    这里是一道小技巧题。
    我们发现,由于MST是唯一的,那么我们就可以发现,任意不相邻的两点之间都有一条新边且这条新边正好是树上两点间路径最大值+1.
    有点绕口。
    然后,50分就很好打了。
    先上个链剖
    我们暴力枚举任意两点,然后统计答案即可。

    100分呢?
    先从小到大枚举边,把当前的边加入图中。
    然后询问当前边所连通的两个连通块的大小分别是什么。
    然后乘起来即可。
    为什么?
    由于我们是从小到大加入边的,所以我们当前的边两端的点之间若是要连接,那么必定经过当前边。
    而且当前边是两点之间最大的边,所以可以直接乘起来加入答案。
    利用并查集维护连通块大小即可。

    很棒的一个小技巧!

    代码

    uses math;
    var
            i,j,k,l,n,m,num,tot,ans,gs,a,b,c,o,xx,yy,jl,t:longint;
            f,v,x,y,z,father:array[1..150000] of longint;
            size:array[1..150000] of int64;
            answer:int64;
    procedure qsort(l,r:longint);
    var
            i,j:longint;
            mid,k:int64;
    begin
            i:=l;
            j:=r;
            mid:=z[(i+j) div 2];
            repeat
                    while (z[i]<mid) do inc(i);
                    while (z[j]>mid) do dec(j);
                    if i<=j then
                    begin
                            k:=z[i];
                            z[i]:=z[j];
                            z[j]:=k;
                            k:=x[i];
                            x[i]:=x[j];
                            x[j]:=k;
                            k:=y[i];
                            y[i]:=y[j];
                            y[j]:=k;
                            inc(i);
                            dec(j);
                    end;
            until i>j;
            if l<j then qsort(l,j);
            if r>i then qsort(i,r);
    end;
    function getfather(x:longint):longint;
    begin
            if father[x]=x then exit(x);
            father[x]:=getfather(father[x]);
            exit(father[x]);
    end;
    begin
            readln(t);
            while t>0 do
            begin
            dec(t);
            readln(n);
            answer:=0;
            for i:=1 to n-1 do
            begin
                    readln(x[i],y[i],z[i]);
                    answer:=answer+z[i];
            end;
            qsort(1,n-1);
            for i:=1 to n do
            begin
                    father[i]:=i;
                    size[i]:=1;
            end;
            o:=0;
            for i:=1 to n-1 do
            begin
                    xx:=getfather(x[i]);
                    yy:=getfather(y[i]);
                    father[xx]:=yy;
                    answer:=answer+(size[xx]*size[yy]-1)*(z[i]+1);
                    size[yy]:=size[yy]+size[xx];
            end;
            writeln(answer);
            end;
    end.
    
  • 相关阅读:
    【MongoDB初识】-结合C#简单使用,驱动2.x
    【NuGet】打包上传一条龙服务
    【NuGet】搭建自己团队或公司的NuGet
    【MongoDB初识】-其他操作
    【MongoDB初识】-条件操作符
    【MongoDB初识】-增删改
    【MongoDB初识】-安装篇
    【面试题】-100盏灯
    【微信开发】一获取用户授权(静默授权方式)
    XML序列化及反序列化
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148370.html
Copyright © 2011-2022 走看看