P1084 [NOIP2012 提高组] 疫情控制

一棵树 n 个节点  初始m个军队驻扎在若干个点,问最短什么时候 所有从rt==1 到 叶节点 的路全部封死

》因为是树-> 贪心->越上面越好

》答案具有单调性 越大越好-> 二分(准确即可)

》》pre_bfs ->fa[][],dis[][]  // shangyi 1.一定到不了直接标记 2.超过的限制待定 存储//  dfs->有多少没有被占领的dep==2的子节点  标记//  

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
#define ll long long
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=5e4+10 ;

pair<ll,int> h[maxn];

ll dis[maxn<<1][30],l,r=1,ans;
int fa[maxn][30],dep[maxn],query[maxn],sta[maxn],need[maxn],htot,tim[maxn],ttot,ned[maxn],ntot;
int head[maxn],to[maxn<<1],nxt[maxn<<1],w[maxn<<1],tot;
int n,m,ok;

void add(int u,int v,int val){
    to[++tot]=v,nxt[tot]=head[u],head[u]=tot,w[tot]=val;
}
void bfs()
{
    queue<int> q; q.push(1),dep[1]=1;
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=head[u];i;i=nxt[i])
        {
            int v=to[i]; if(dep[v]) continue; dep[v]=dep[u]+1;
            fa[v][0]=u, dis[v][0]=w[i];
            for(int j=1;j<=21;j++)
                fa[v][j]=fa[fa[v][j-1]][j-1],dis[v][j]=dis[v][j-1]+dis[fa[v][j-1]][j-1];        
            q.push(v);//
        }
    }
}
int dfs(int u)
{
    int leaf=1;
    if(sta[u]==1) return 1;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i]; if(dep[v]<dep[u]) continue;
        leaf=0;
        if(dfs(v)==0) return 0;
    }
    if(leaf==1) return 0;
    return 1;
}

int check(ll lim)
{
    memset(ned,0,sizeof(ned));
    memset(tim,0,sizeof(tim));
    memset(sta,0,sizeof(sta));
    memset(need,0,sizeof(need));
    memset(h,0,sizeof(h));
    ntot=ttot=htot=0;
    
    for(int i=1;i<=m;i++)
    {
        ll tmp=0;int x=query[i];
        for(int j=21;j>=0;j--)//
        {
            if(fa[x][j]>1&&tmp+dis[x][j]<=lim)
                tmp+=dis[x][j],x=fa[x][j];
        }
        if(fa[x][0]==1&&tmp+dis[x][0]<=lim)
            h[++htot]=make_pair(lim-tmp-dis[x][0],x);//
        else sta[x]=1;
    }
    
    for(int i=head[1];i;i=nxt[i]){
        int v=to[i];
        if(dfs(v)==0) need[v]=1;//
    }
    for(int i=1;i<=htot;i++){
        if(need[h[i].second]==1&&h[i].first<=dis[h[i].second][0]) need[h[i].second]=0,sta[h[i].second]=1;
        else tim[++ttot]=h[i].first;
    }
    for(int i=head[1];i;i=nxt[i]){
        int v=to[i];
        if(need[v]==1) ned[++ntot]=dis[v][0];
    }
    
    if(ntot>ttot) return 0;
    sort(tim+1,tim+1+ttot),sort(ned+1,ned+1+ntot);
    int i=1,j=1;
    while(i<=ttot&&j<=ntot){
        if(tim[i]>=ned[j]){ i++,j++;}
        else i++;
    }
    if(j<=ntot) return 0;
    else return 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n-1;i++){
        int u,v,val;cin>>u>>v>>val;
        add(u,v,val),add(v,u,val);
        r+=val;
    }
    bfs();
    cin>>m;
    for(int i=1;i<=m;i++) cin>>query[i];
    
    while(l<=r)
    {
        ll mid=l+r>>1;
        if(check(mid)){
            r=mid-1;
            ans=mid;
            ok=1;
        } 
        else l=mid+1;
    }
    if(ok==0){ cout<<"-1\n"; return 0; }
    cout<<ans<<'\n';
    
    return 0;
}

 

posted @ 2023-09-10 15:00  JMXZ  阅读(11)  评论(0)    收藏  举报