博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动态最小生成树讲解
阅读量:7063 次
发布时间:2019-06-28

本文共 4472 字,大约阅读时间需要 14 分钟。

  动态最小生成树是一类要求给定图,对于图的边有删除,插入,修改边权操作,满足查询MST(Minimum Spanning Tree )的问题。

  在这里我们考虑修改边的操作,删除可以看成是将边权设成INF,插入可以看做是将一条INF的边边权赋值。

  那么假设我们有q个询问,每个询问修改一条边的权值。

  对于q个询问里修改的边,我们设这个边集为Q,全集为E,那么对于E-Q中的边,做一遍MST,MST中的边集设为G,那么对于E-Q-G中的边,不论询问怎么改变,这些边都不会在MST中,所以我们可以删除这些边,这时全集E不包括刚才删除的边,全集中的边的数量变成了n+q,n为MST中必要的边,q为询问中的边。之后将Q中的边的边权都赋值为-ING,这时做一遍MST,如果E-Q的边在MST中,这时代表就算修改的边最小时这些边也要选,也就是这些边是保证MST连通性的必要的边,这些边我们也没有必要考虑,因为必须要选,所以将这条边连接的两个点合并成一个点,可以用并查集维护。那么这些操作之后,我们将边的规模变成了q的,点的规模变成了q的。那么我求出来询问包括1-q的情况了,在剩下的这张图(规模变小了)上,将询问的范围变成1-q>>1和q<<1-q,再递归的做下去,因为询问的不断地变小,每次都会有更多的边被缩掉(在第二次做MST时可以缩掉的边),每次边的规模都变成了q/2^dep,这样一共会有log2q层,每层做MST是qlog2q的,那么总的时间复杂度就是q(log2q,我们递归的时候不用每次都排序,可以保存原来有序的边集,所以可以去掉一个log2q,这样时间复杂度就变成了qlog2q。

  练习题,bzoj 2001 

/**************************************************************    Problem: 2001    User: BLADEVIL    Language: Pascal    Result: Accepted    Time:14456 ms    Memory:37024 kb****************************************************************/ //By BLADEVILtype    node                            =record    cnt                             :longint;    a,b                             :array[1..250000]of longint;    end;     var    e                               :array[1..18] of node;    fa                              :array[1..20000]of longint;    x, y, data, tdata               :array[0..50000]of longint;    num, cha, ord, opt              :array[0..50000]of longint;    i , n, m, q                     :longint;    ans                             :int64;     procedure swap(var a,b:longint);var    t                               :longint;begin    t:=a;    a:=b;    b:=t;end; procedure qsort(left,right:longint);var    i, j, bj                        :longint;begin    i:=left;    j:=right;    bj:=data[ord[(i+j) shr 1]];    while i<=j do    begin        while data[ord[i]]
bj do dec(j);        if i<=j then        begin            swap(ord[i],ord[j]);            inc(i); dec(j);        end;    end;    if j>left then qsort(left,j);    if i
tmp do tmp:=fa[tmp];    while fa[a]<>tmp do    begin        inc(e[dep].cnt);        e[dep].a[e[dep].cnt]:=a;        e[dep].b[e[dep].cnt]:=fa[a];        fa[a]:=tmp;        a:=e[dep].b[e[dep].cnt];    end;    exit(tmp);end; procedure combine(a,b:longint);begin    a:=getfather(a);    b:=getfather(b);    inc(e[dep].cnt);    e[dep].a[e[dep].cnt]:=a;    e[dep].b[e[dep].cnt]:=fa[a];    fa[a]:=b;end; procedure recover(a:longint);begin    while e[dep].cnt<>a do    begin        fa[e[dep].a[e[dep].cnt]]:=e[dep].b[e[dep].cnt];        dec(e[dep].cnt);    end;end; begin    tans:=ans;    e[dep].cnt:=0;    if left=right then    begin        data[num[left]]:=cha[left];        tdata[num[left]]:=cha[left];        qsort(1,m);        for i:=1 to m do        if getfather(x[ord[i]])<>getfather(y[ord[i]]) then        begin            combine(x[ord[i]],y[ord[i]]);            ans:=ans+data[ord[i]];        end;        writeln(ans);        recover(0);        ans:=tans;        exit;    end;    tm:=m;    for i:=left to right do        data[num[i]]:=-maxlongint;    qsort(1,m);    opt[0]:=0;    for i:=1 to m do        if getfather(x[ord[i]])<>getfather(y[ord[i]]) then        begin            combine(x[ord[i]],y[ord[i]]);            if data[ord[i]]<>-maxlongint then            begin                inc(opt[0]);                opt[opt[0]]:=ord[i];            end;        end;    recover(0);    for i:=1 to opt[0] do    begin        combine(x[opt[i]],y[opt[i]]);        ans:=ans+data[opt[i]];    end;    tcnt:=e[dep].cnt;    for i:=left to right do        data[num[i]]:=maxlongint;    qsort(1,m);    opt[0]:=0;    for i:=1 to m do        if getfather(x[ord[i]])<>getfather(y[ord[i]]) then            combine(x[ord[i]],y[ord[i]]) else                if data[ord[i]]<>maxlongint then                begin                    inc(opt[0]);                    opt[opt[0]]:=i;                end;    for i:=opt[0] downto 1 do    begin        swap(ord[opt[i]],ord[m]);        dec(m);    end;    recover(tcnt);    for i:=left to right do        data[num[i]]:=tdata[num[i]];    work(dep+1,left,(left+right) shr 1);    work(dep+1,(left+right) shr 1 +1,right);    m:=tm;    ans:=tans;    recover(0);end; begin    readln(n,m,q);    for i:=1 to n do        fa[i]:=i;    for i:=1 to m do    begin        readln(x[i],y[i],data[i]);        tdata[i]:=data[i];        ord[i]:=i;    end;    for i:=1 to q do        readln(num[i],cha[i]);    work(1,1,q);end.

 

转载于:https://www.cnblogs.com/BLADEVIL/p/3512644.html

你可能感兴趣的文章
python
查看>>
CentOS中与网络相关的常用
查看>>
html5的Message信息提示框
查看>>
Android清除本地数据缓存代码
查看>>
玩转Vim 编辑器
查看>>
vue中的computed(计算属性)和watch(监听属性)的特点,以及深度监听
查看>>
cef_binary_3.2623.1401.gb90a3be
查看>>
log4j
查看>>
原生JS获取元素的位置与尺寸
查看>>
SOA_环境安装系列1_Oracle SOA Suite11g安装总括(案例)
查看>>
DBMS_JOBS
查看>>
Python基础3:函数
查看>>
devgridContral
查看>>
[转]notepad++正则表达式替换字符串详解
查看>>
最近踩坑汇总
查看>>
骨牌(/棋子?)覆盖问题
查看>>
浅谈差分
查看>>
LEFT JOIN、RIGHT JOIN、INNER JOIN、FULL JOIN 使用
查看>>
谈谈 oc原生和跳转h5 页面 来回切换的功能
查看>>
【二维树状数组】【CF10D】 LCIS
查看>>