luoguP1084 疫情控制(题解)(搜索+贪心)

Posted eternal风度

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP1084 疫情控制(题解)(搜索+贪心)相关的知识,希望对你有一定的参考价值。

luoguP1084 疫情控制 题目

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define il inline
#define rg register
#define ll long long
#define N 60000
#define inf 2147483647
using namespace std;

int n,m,hd[N],cnt,u,v,w;
int c,idx[N];
int le,ri=500000;
int dis[N][20],up[N][20];
int ok[N],use[N],vis[N];
struct S{
    int res,idx;
}ne[N],to[N];
struct T{
    int nt,to,w;
}edge[N<<1];
il void re(rg int &x);
void add(rg int fm,rg int to,rg int w);
void ST(rg int i,rg int fa);
int check(rg int lim);
int Dfs(rg int u,rg int fa);
int Cmp(const S &x,const S &y);

int main()
{
    re(n);
    for(rg int i=1;i<n;++i)
    {
        re(u),re(v),re(w);
        add(u,v,w),add(v,u,w);
        if(u==1||v==1)c++;
    }
    re(m);
    if(m<c){cout<<-1;return 0;}
    for(rg int i=1;i<=m;++i)
        re(idx[i]);
        
    ST(1,0);
    for(rg int k=1;k<=19;++k)
    {
        for(rg int i=1;i<=n;++i)
        {
            up[i][k]=up[up[i][k-1]][k-1];
            dis[i][k]=dis[up[i][k-1]][k-1]+dis[i][k-1];
        }
    }
    while(le<ri)
    {
        rg int mid=((le+ri)>>1);
        if(check(mid))ri=mid;
        else le=mid+1;
    }
    cout<<le;
    
    return 0;
}

il void re(rg int &x)
{
    rg int res=0;rg int w=1;char c=getchar();
    while((c<0||c>9)&&c!=-)c=getchar();
    if(c==-)w=-1,c=getchar();
    while(c>=0&&c<=9)res=(res<<3)+(res<<1)+c-0,c=getchar();
    x=w*res;
}
void add(rg int fm,rg int to,rg int w)
{
    edge[++cnt].nt=hd[fm];
    edge[cnt].to=to;
    edge[cnt].w=w;
    hd[fm]=cnt;
}
void ST(rg int i,rg int fa)
{
    up[i][0]=fa;
    for(rg int k=hd[i];k;k=edge[k].nt)
    {
        rg int qw=edge[k].to;
        if(qw==fa)continue;
        dis[qw][0]=edge[k].w;
        ST(qw,i);
    }
}
int check(rg int lim){
    memset(ok,0,sizeof(ok));
    memset(use,0,sizeof(use));
    memset(vis,0,sizeof(vis));
    rg int cnt1=0,cnt2=0;
    rg int top=1;
    for(rg int i=1;i<=m;++i){
        rg int res=lim,u=idx[i];
        for(rg int k=19;k>=0;--k){
            if(up[u][k]&&up[u][k]!=1&&res>=dis[u][k])
                res-=dis[u][k],u=up[u][k];
        }
        if(up[u][0]==1&&res>dis[u][0])
        {
            to[++cnt1].res=res-dis[u][0];
            to[cnt1].idx=u;
        }
        else ok[u]=1;
    }
    Dfs(1,0);
    for(rg int k=hd[1];k;k=edge[k].nt){
        rg int qw=edge[k].to;
        if(!ok[qw]){
            ne[++cnt2].res=dis[qw][0];
            ne[cnt2].idx=qw;
        }
    }
    sort(to+1,to+cnt1+1,Cmp);
    sort(ne+1,ne+cnt2+1,Cmp);
    if(cnt1<cnt2)return 0;
    for(rg int i=1;i<=cnt1;++i)
    {
        if(!vis[to[i].idx])
        {
            vis[to[i].idx]=1;
            continue;
        }
        while(vis[ne[top].idx])top++;
        if(to[i].res>=ne[top].res)
        {
            vis[ne[top].idx]=1,top++;
            continue;
        }
        if(top>cnt2)break;
    }
    while(vis[ne[top].idx])top++;
    if(top<=cnt2)return 0;
    return 1;
}
int Dfs(rg int u,rg int fa)
{
    rg int temp=1,flag=0;
    for(rg int k=hd[u];k;k=edge[k].nt)
    {
        rg int qw=edge[k].to;
        if(qw==fa)continue;
        flag++,temp&=Dfs(qw,u);
    }
    if(!flag)temp=0;
    ok[u]=(ok[u]|temp);
    if(ok[u]&&up[u][0]==1)
        vis[u]=1;
    return ok[u];
}
int Cmp(const S &x,const S &y){return x.res<y.res;}

 

以上是关于luoguP1084 疫情控制(题解)(搜索+贪心)的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P1084 疫情控制 | 二分答案 贪心

P1084 [NOIP2012 提高组] 疫情控制(倍增&贪心&二分)

洛谷 P1084 疫情控制 题解

洛谷 P1084 [NOIP2012 提高组] 疫情控制(二分,倍增,贪心)

P1084 疫情控制

P1084 疫情控制