JZOJ 3104.疫情控制

Problem 3104

Description

JZOJ 3104.疫情控制_第1张图片

Input

JZOJ 3104.疫情控制_第2张图片

Output

这里写图片描述

Sample Input

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

Sample Output

3

Data Constraint

JZOJ 3104.疫情控制_第3张图片

Solution

一看这道题,一定要用数组模拟链表啦~,因为n=50000,用领接表的话空间早就爆了……
体型:贪心+二分+树
我们可以构造一棵树,然后让全部的军队在时间允许之下(设当前时间为mid)尽量向父亲节点跑,跑到首都为止。如果他不够时间再跑回从那个点跑到首都的那个点,则就将这个军队停留在这个点。证明过程到时候写。
这时我们将能留在首都的点、剩余没有分配军队的深度为1的点与首都的边的权值从小到大排个序,再一对一匹配。如果不成功,则看看下一个留在首都的点能不能与当前这条边匹配。如果还剩下有没有匹配到的边,则证明答案比mid大。
最后输出l就可以了。

Code

var next,head,num,deep,b,go,f,g,h1,h2:array[0..100001] of int64;
    fa,d,d1:array[0..50001,1..2] of int64;
    c,e,e1:array[0..50001,1..3] of int64;
    a,h,g1,g2:array[0..50001] of boolean;
    i,j,k,l,r,mid,n,m,t,s,xx,yy,x,y,tot,o,wz:longint;
    ans,min:int64;
    p:boolean;
procedure qsort(l,r:longint);
var i,j:longint;
    t:array[1..3] of int64;
    mid:int64;
begin
    i:=l;
    j:=r;
    mid:=e1[(l+r)div 2,3];
    repeat
        while e1[i,3]<mid do inc(i);
        while e1[j,3]>mid do dec(j);
        if i<=j then
        begin
            t:=e1[i];
            e1[i]:=e1[j];
            e1[j]:=t;
            inc(i);
            dec(j);
        end;
    until i>j;
    if l<j then qsort(l,j);
    if i<r then qsort(i,r);
end;
procedure q1(l,r:longint);
var i,j:longint;
    t:array[1..2] of int64;
    mid:int64;
begin
    i:=l;
    j:=r;
    mid:=d1[(l+r)div 2,2];
    repeat
        while d1[i,2]<mid do inc(i);
        while d1[j,2]>mid do dec(j);
        if i<=j then
        begin
            t:=d1[i];
            d1[i]:=d1[j];
            d1[j]:=t;
            inc(i);
            dec(j);
        end;
    until i>j;
    if l<j then q1(l,j);
    if i<r then q1(i,r);
end;
function mi(a,b:int64):int64;
begin
    if a<b then exit(a) else exit(b);
end;
function dg(k:longint):boolean;
var i:longint;
    p1:boolean;
begin
    dg:=false;
    i:=next[k];
    h[k]:=true;
    if a[k] and (k<>1) then exit(true);
    if g[k]<>1 then a[k]:=true;
    while i>0 do
    begin
        if not h[go[i]] then
        begin
            p1:=dg(go[i]);
            a[k]:=a[k] and p1;
        end;
        i:=head[i];
    end;
end;
function dg1(x:int64):longint;
var i:longint;
    p:longint;
begin
    i:=next[x];
    dg1:=h1[x];
    h[x]:=true;
    while i>0 do
    begin
        if not h[go[i]] then
        begin
            p:=dg1(go[i]);
            h2[x]:=h2[x]+h2[go[i]];
        end;
        i:=head[i];
    end;
end;
procedure lb(x,y,z:int64);
begin
    inc(tot);
    go[tot]:=y;
    inc(g[y]);
    head[tot]:=next[x];
    next[x]:=tot;
    num[tot]:=z;
end;
procedure bs(x,y:int64);
var i:longint;
begin
    i:=next[x];
    deep[x]:=y;
    while i>0 do
    begin
        if (deep[go[i]]=0)and(go[i]<>1) then
        begin
            bs(go[i],y+1);
            fa[go[i],1]:=x;
            fa[go[i],2]:=num[i];
        end;
        i:=head[i];
    end;
end;
function get(n:longint):longint;
begin
    if f[n]=0 then exit(n)
    else
    begin
        f[n]:=get(f[n]);
        get:=f[n];
    end;
end;
function lca(x,y:int64):int64;
var ans:int64;
begin
    ans:=0;
    while (deep[x]>deep[y]) do
    begin
        ans:=ans+fa[x,2];
        x:=fa[x,1];
    end;
    while (deep[y]>deep[x]) do
    begin
        ans:=ans+fa[y,2];
        y:=fa[y,1];
    end;
    if x=y then exit(ans);
    while x<>y do
    begin
        ans:=ans+fa[x,2];
        x:=fa[x,1];
        ans:=ans+fa[y,2];
        y:=fa[y,1];
    end;
    exit(ans);
end;
begin
    readln(n);
    for i:=1 to n-1 do
    begin
        read(c[i,1],c[i,2],c[i,3]);
        if c[i,1]=1 then
        begin
            inc(d[0,1]);
            d[d[0,1],1]:=c[i,2];
            d[d[0,1],2]:=c[i,3];
        end else
        if c[i,2]=1 then
        begin
            inc(d[0,1]);
            d[d[0,1],1]:=c[i,1];
            d[d[0,1],2]:=c[i,3];
        end;
    end;
    for i:=1 to n do
    begin
        x:=get(c[i,1]);
        y:=get(c[i,2]);
        if x<>y then
        begin
            f[x]:=y;
            lb(c[i,1],c[i,2],c[i,3]);
            lb(c[i,2],c[i,1],c[i,3]);
        end;
    end;
    bs(1,0);
    readln(m);
    for i:=1 to m do
    begin
        read(b[i]);
        inc(h1[b[i]]);
    end;
    h2:=h1;
    dg1(1);
    if m<d[0,1] then
    begin
        writeln(-1);
        halt;
    end;
    l:=0;
    r:=1000000000;
    deep[0]:=0;
    while l<r do
    begin
        mid:=(l+r)div 2;
        fillchar(e1,sizeof(e1),0);
        fillchar(d1,sizeof(d1),0);
        fillchar(a,sizeof(a),0);
        fillchar(e,sizeof(e),0);
        fillchar(h,sizeof(h),0);
        fillchar(g1,sizeof(g1),0);
        fillchar(g2,sizeof(g2),0);
        for i:=1 to m do
        begin
            x:=b[i];
            ans:=0;
            while deep[x]>0 do
            begin
                if (deep[x]=1) then
                    if ans+fa[x,2]<=mid then e[i,2]:=x;
                ans:=ans+fa[x,2];
                if ans>mid then break;
                x:=fa[x,1];
            end;
            e[i,1]:=x;
            e[i,3]:=mid-ans;
            a[x]:=true;
            if e[i,3]>=fa[e[i,2],2] then
            begin
                g1[i]:=true;
                inc(e1[0,1]);
                e1[e1[0,1]]:=e[i];
            end else
            if e[i,2]<>0 then
            begin
                a[e[i,2]]:=true;
                g2[i]:=true;
            end;
        end;
        a[1]:=dg(1);
        for i:=1 to d[0,1] do
            if not a[d[i,1]] then
            begin
                inc(d1[0,1]);
                d1[d1[0,1]]:=d[i];
            end;
        for i:=1 to m do
            if not g1[i] then
            begin
                if g2[i] and (h2[e[i,2]]>1) then
                begin
                    inc(e1[0,1]);
                    e1[e1[0,1]]:=e[i];
                end;
            end;
        q1(1,d1[0,1]);
        qsort(1,e1[0,1]);
        p:=false;
        i:=1;
        j:=0;
        while (i<=d1[0,1]) do
        begin
            inc(j);
            while (e1[j,3]<d1[i,2])and(j<=e1[0,1]+1) do inc(j);
            if j>e1[0,1] then
            begin
                p:=true;
                break;
            end;
            inc(i);
        end;
        if p then l:=mid+1 else r:=mid;
    end;
    writeln(l);
end.

这个标写的不是很好,希望各位大神能够雅正。
——2016.3.30 By Wzy

你可能感兴趣的:(Pascal程序)