zoukankan      html  css  js  c++  java
  • bzoj 1015 并查集

    逆向思维,先将整张图以最后所有要求的点毁掉的状态建图,然后倒着

    加点就行了,用并查集维护连通块

    /**************************************************************
        Problem: 1015
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:2588 ms
        Memory:16340 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, m, k                     :longint;
        flag                        :array[0..500010] of boolean;
        pre, other, last            :array[0..500010] of longint;
        delete, x, y, ans           :array[0..500010] of longint;
        father                      :array[0..500010] of longint;
        l                           :longint;
         
         
    procedure connect(x,y:longint);
    begin
        inc(l);
        pre[l]:=last[x];
        last[x]:=l;
        other[l]:=y;
    end;
     
    procedure init;
    var
        i                           :longint;
    begin
        read(n,m);
        for i:=1 to m do
        begin
            read(x[i],y[i]);
            connect(x[i],y[i]);
            connect(y[i],x[i]);
        end;
        read(k);
        for i:=1 to k do
        begin
            read(delete[i]);
            flag[delete[i]]:=true;
        end;
    end;
     
    function getfather(x:longint):longint;
    begin
        if father[x]=x then exit(x);
        father[x]:=getfather(father[x]);
        exit(father[x]);
    end;
     
    procedure main;
    var
        i                           :longint;
        fa, fb                      :longint;
        cur                         :longint;
        q, p                        :longint;
         
    begin
        for i:=0 to n-1 do father[i]:=i; 
        for i:=1 to m do
        begin
            if (not flag[x[i]]) and (not flag[y[i]]) then
            begin
                fa:=getfather(x[i]); fb:=getfather(y[i]);
                if fa<>fb then father[fa]:=fb;
            end;
        end;
        for i:=0 to n do if (not flag[i]) and (father[i]=i) then inc(ans[k+1]); 
        for i:=k downto 1 do
        begin
            cur:=delete[i];
            ans[i]:=ans[i+1];
            q:=last[cur];
            inc(ans[i]);
            while q<>0 do
            begin
                p:=other[q];
                if not flag[p] then
                begin  
                    fa:=getfather(p);
                    if fa<>cur then
                    begin
                        dec(ans[i]);
                        father[fa]:=cur;
                    end;
                end;
                q:=pre[q];
            end;
            flag[cur]:=false;
        end;
        for i:=1 to k+1 do writeln(ans[i]);
    end;
     
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    初探动态规划(DP)
    高精度压位
    Poi写文件时报java.io.IOException: Read error
    mysql合并和时间函数
    线程池子线程先执行再执行主线程
    linux常用命令
    使用线程池应该注意的问题
    分页查询千万级数据慢
    待簳的题......
    记录脑残失误,让达摩克利斯之剑永远高悬
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3496046.html
Copyright © 2011-2022 走看看