zoukankan      html  css  js  c++  java
  • bzoj 2753 最小生成树变形

    我们根据高度建图,将无向边转化为有向边

    首先对于第一问,直接一个bfs搞定,得到ans1

    然后第二问,我们就相当于要求找到一颗最小生成树,

    满足相对来说深度小的高度大,也就是要以高度为优先级

    假设现在有一种添边的方案(一共添ans1-1条,类似于Kruskal的过程

    那么对于添边,我们可以看做是现有一颗树,通过连接一条边将一个点加入到树里的过程

    那么对于添加一个点,假设有一种方案先加入X,然后加入Y,HIGH[X]<HIGH[Y]那么肯定

    可以找到另一种添加方式,先加入Y,再加入X,因为Y比X高,也就是既然能先加X,X肯定不

    影响Y的合法性,也就是以高度为优先级,保证了合法性

    那么我们在做Kruskal 的排序的时候,只需要以点(X——>Y,说的是Y点)的高度为第一关键字,

    边长为第二关键字就好了。

    后来看了网上别人的思路,上面我写的加边的那一部分,可以通过prim来理解,prim就是现在有一个点的集合

    然后在剩下的点里找到距离集合最短的一个点加进来,后面高度优先级的证明类似。

    /**************************************************************
        Problem: 2753
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:26668 ms
        Memory:96420 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, m                    :int64;
        high                    :array[0..100010] of int64;
        pred, succ              :array[0..2000010] of int64;
        len                     :array[0..2000010] of int64;
        pre, other, last        :array[0..2000100] of int64;
        l                       :int64;
        que                     :array[0..100010] of int64;
        ans1, ans2              :int64;
        flag                    :array[0..100010] of boolean;
        father                  :array[0..100010] of int64;
         
    procedure swap(var a,b:int64);
    var
        c                       :int64;
    begin
        c:=a; a:=b; b:=c;
    end;
     
    procedure connect(x,y:int64);
    begin
        inc(l);
        pre[l]:=last[x];
        last[x]:=l;
        other[l]:=y;
    end;
         
    procedure init;
    var
        i                       :longint;
        x, y, z                 :int64;
         
    begin
        read(n,m);
        for i:=1 to n do read(high[i]);
        for i:=1 to m do
        begin
            read(x,y,z);
            if high[x]<high[y] then swap(x,y);
            pred[i]:=x; succ[i]:=y; len[i]:=z;
            connect(x,y);
            if high[x]=high[y] then connect(y,x);
        end;
    end;
     
    procedure bfs;
    var
        h, t                    :int64;
        cur                     :int64;
        q, p                    :int64;
        i                       :longint;
    begin
        h:=0; t:=1;
        que[1]:=1;
        flag[1]:=true;
        while h<t do
        begin
            inc(h);
            cur:=que[h];
            q:=last[cur];
            while q<>0 do
            begin
                p:=other[q];
                if not flag[p] then
                begin
                    inc(t);
                    flag[p]:=true;
                    que[t]:=p;
                end;
                q:=pre[q];  
            end;
        end;
        ans1:=t;
    end;
     
    procedure qs(l,h:int64);
    var
        i, j, xx, yy            :int64;
    begin
        i:=l; j:=h; 
        xx:=high[succ[(i+j) div 2]];
        yy:=len[(i+j) div 2];
        while i<j do
        begin
            while (high[succ[i]]>xx) or (high[succ[i]]=xx) and (len[i]<yy) do inc(i);
            while (high[succ[j]]<xx) or (high[succ[j]]=xx) and (len[j]>yy) do dec(j);
            if i<=j then
            begin
                swap(pred[i],pred[j]);
                swap(succ[i],succ[j]);
                swap(len[i],len[j]);
                inc(i); dec(j);
            end;
        end;
        if i<h then qs(i,h);
        if j>l then qs(l,j);
    end;
     
    function getfather(x:int64):int64;
    begin
        if father[x]=x then exit(x);
        father[x]:=getfather(father[x]);
        exit(father[x]);
    end;
     
    procedure main;
    var
        a, b, fa, fb            :int64;
        i                       :longint;
         
    begin
        bfs;
        for i:=1 to n do father[i]:=i;
        qs(1,m);
        for i:=1 to m do
        begin
            a:=pred[i]; b:=succ[i];
            if (not flag[a]) or (not flag[b]) then continue;
            fa:=getfather(a); fb:=getfather(b);
            if (fa<>fb)then
            begin
                father[fb]:=fa;
                ans2:=ans2+len[i];
            end;
        end;
        writeln(ans1,' ',ans2);
    end;
     
         
    begin
        init;
        main;
    end.
  • 相关阅读:
    python 多线程测试
    python 多线程join()
    python 多线程 t.setDaemon(True):
    线程锁
    python 多线程
    模板渲染和参数传递.
    求两个数组的交集
    java数组并集/交集/差集(补集)
    java各种集合的线程安全
    页面跳转和重定向
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3468586.html
Copyright © 2011-2022 走看看