[洛谷P1084]疫情控制:二分答案+倍增+贪心

分析:

待会儿补。

代码:

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
typedef long long LL;

const int MAXN=50005;

int n,m,ecnt,head[MAXN];
struct Edge{
    int to,nxt,w;
}e[MAXN<<1];
struct Guard{
    int pos;LL res;
    friend bool operator < (Guard x,Guard y){
        return x.res<y.res;
    }
}a[MAXN];
int f[MAXN][20];
LL dis[MAXN][20];
int Belong[MAXN],untag[MAXN],siz;
bool tag[MAXN];

inline void add_edge(int bg,int ed,int val){
    ecnt++;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].w=val;
    head[bg]=ecnt;
}

inline bool cmp(int x,int y){
    return dis[x][0]<dis[y][0];
}

void dfs1(int x,int pre,int len){
    if(pre==1) Belong[x]=x;
    else Belong[x]=Belong[pre];
    f[x][0]=pre,dis[x][0]=len;
    for(int i=1;i<=18;i++){
        f[x][i]=f[f[x][i-1]][i-1];
        dis[x][i]=dis[x][i-1]+dis[f[x][i-1]][i-1];
    }
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(ver==pre) continue;
        dfs1(ver,x,e[i].w);
    }
}

void dfs2(int x){
    bool flag=1,isleaf=1;
    for(int i=head[x];i;i=e[i].nxt){
        int ver=e[i].to;
        if(ver==f[x][0]) continue;
        isleaf=0;
        dfs2(ver);
        if(!tag[ver]) flag=0;
    }
    if(flag&&!isleaf) tag[x]=1;
}

inline bool check(LL mid){
    memset(tag,0,sizeof tag);
    for(register int i=1;i<=m;i++){
        int now=a[i].pos;LL Res=mid;
        a[i].res=-1;
        for(register int j=18;j+1;j--){
            if(dis[now][j]>Res) continue;
            if(f[now][j]==0) continue;
            Res-=dis[now][j];
            now=f[now][j];
            if(now==1){
                a[i].res=Res;
                break;
            }
        }
        if(a[i].res!=-1) continue;
        tag[now]=1;
    }
    dfs2(1);
    if(tag[1]) return 1;
    siz=0;
    for(register int i=head[1];i;i=e[i].nxt){
        int ver=e[i].to;
        if(!tag[ver]) untag[++siz]=ver;
    }
    std::sort(untag+1,untag+siz+1,cmp);
    std::sort(a+1,a+m+1);
    register int poi=1;
    for(register int i=1;i<=m;i++){
        if(a[i].res==-1) continue;
        if(!tag[Belong[a[i].pos]]&&a[i].res<dis[Belong[a[i].pos]][0]){
            tag[Belong[a[i].pos]]=1;
        }
        else if(a[i].res>=dis[untag[poi]][0]){
            tag[untag[poi++]]=1;
            if(poi>siz) return 1;
        }
        while(poi<=siz&&tag[untag[poi]]==1) poi++;
        if(poi>siz) return 1;
    }
    return 0;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        add_edge(u,v,w);
        add_edge(v,u,w);
    }
    dfs1(1,0,0);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d",&a[i].pos);
    LL l=0,r=5e13+1,ans=-1;
    while(l<=r){
        LL mid=((l+r)>>1);
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9688002.html