P1084 疫情控制

——————————————————————————————————————————————————————

邪门的贪心,需要处理很多情况,还要注意二分

还要注意标记下传

还要处理倍增

还要双指针

还是一道很好的题

——————————————————————————————————————

#include<bits/stdc++.h>
using namespace std;
struct node{int nxt,dis,to;}eg[51000*2];
#define ll long long
int n,head[51000],m,ne,fa[51000][22],d[51000][22],a,b,c,id[51000],tag[51000];
void adde(int from,int to,int dis)
{eg[++ne].to=to;eg[ne].dis=dis;eg[ne].nxt=head[from];head[from]=ne;}
struct nd{int it,re;}num[51000];
struct nod{int ti,val;}q[51000];
int cmp(nd x,nd y){return x.re<y.re;}
int cmp2(nod a,nod b){return a.val<b.val;}
void dfs(int u,int f){
    for(int i=head[u];i;i=eg[i].nxt)
    {
        int v=eg[i].to;
        if(v==f)continue;
        fa[v][0]=u;d[v][0]=eg[i].dis;
        dfs(v,u);
    }
}
void dfs2(int u,int f){
    if(tag[u])return;
    bool flg=0;tag[u]=1;
    for(int i=head[u];i;i=eg[i].nxt)
    {
        int v=eg[i].to;
        if(v==f)continue;
        dfs2(v,u);
        flg=1;
        if(!tag[v])tag[u]=0;
    }
    if(!flg)tag[u]=0;
}
int check(ll w)
{
    memset(tag,0,sizeof(tag));
    int cnt=0,sum=0;
    for(int i=1;i<=m;i++)
    {
        ll rest=w;
        int di=id[i];
        for(int j=16;j>=0;j--)if(rest-d[di][j]>=0&&fa[di][j]>1){rest-=d[di][j];di=fa[di][j];}
        if(fa[di][0]!=1||(rest<d[di][0]))tag[di]=1;
        else {
            num[++cnt].it=di;
            num[cnt].re=rest-d[di][0];
            }    
    }
    dfs2(1,1);
    for(int i=head[1];i;i=eg[i].nxt)
    if(!tag[eg[i].to]){q[++sum].ti=eg[i].to;q[sum].val=eg[i].dis;}
    sort(num+1,num+1+cnt,cmp);
    sort(q+1,q+1+sum,cmp2);
    int pos=1;
    for(int i=1;i<=cnt;++i) {
        if(!tag[num[i].it]) tag[num[i].it]=1;
        else if(num[i].re>=q[pos].val)tag[q[pos].ti]=1;
        while(tag[q[pos].ti]&&pos<=sum) ++pos;
        int t;
        for(t=pos;t<=sum;t++)
        {
            
        }
    }
    return pos>sum;
}
int main()
{
    ll r=0,l=0,mid,ans;
    cin>>n;
    for(int i=1;i<n;i++)
    {cin>>a>>b>>c;adde(a,b,c);adde(b,a,c);r+=c;}
    cin>>m;
    for(int i=1;i<=m;i++)cin>>id[i];
    dfs(1,0);
    for(int i=1;i<=16;i++)for(int j=1;j<=n;j++){fa[j][i]=fa[fa[j][i-1]][i-1];d[j][i]=d[j][i-1]+d[fa[j][i-1]][i-1];    }
    while(l<=r)
    {    mid=(l+r)/2;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans;
}
原文地址:https://www.cnblogs.com/SFWR-YOU/p/11104947.html