luogu P1084疫情控制 二分

链接

luogu

思路

二分。
每个军队在一定的时间内越往上越好。
注意一个军队可以跨过1去帮别的。
把能到1脚下的点都存下来特判。
有一种情况是这个子树内只有一个军队,但这个军队跑去帮别人了。
其他军队来帮这个子树。
就像这样。

四号点的军队还有2秒钟,而且四号点有两个军队。
2号点有一个军队,还有101秒钟。
三号点没有军队。
四号点的一个军队到2,二号点的的军队到三。
这样的2号点放弃内部去外部的条件是什么?
答案是两倍的边权<剩余时间。
不然的话,四号店可以直接去拯救三号点了。

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int _=1e5+7;
const ll oo=0x3f3f3f3f3f3f3f;
int read() {
    int x=0,f=1;char s=getchar();
    for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    return x*f;
}
int n,m,pos[_],fa[_][16],vis[_];
ll sum[_];
struct node {
    int v,nxt,q;
}e[_<<1];
int head[_],tot;
void add(int u,int v,int q) {
    e[++tot].v=v;
    e[tot].q=q;
    e[tot].nxt=head[u];
    head[u]=tot;
}
void init(int u,int f,ll tot) {
    fa[u][0]=f;
    sum[u]=tot;
    for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(v==f) continue;
        init(v,u,tot+e[i].q);
    }
}
int ok[_];
bool dfs(int u,int fa) {
    if(vis[u]) return 1;
    int siz=0;
    for(int i=head[u];i;i=e[i].nxt) {
        int v=e[i].v;
        if(v==fa) continue;
        siz++;
        if(!dfs(v,u)) return 0;
    } return siz;
}
vector<int> dsr[_];
bool cmp(int a,int b) {return sum[a]<sum[b];}
ll nb[_],cb[_];
bool check(ll mid) {
    for(int i=1;i<=n;++i) vis[i]=ok[i]=0;
    for(int i=head[1];i;i=e[i].nxt) dsr[e[i].v].clear();
    for(int i=1;i<=m;++i) {
        int p=pos[i];
        for(int j=15;j>=0;--j)
            if(sum[pos[i]]-sum[fa[p][j]]<=mid)
                p=fa[p][j];
        if(fa[p][0]!=1) vis[p]++;
        else dsr[p].push_back(pos[i]);
    }
    for(int i=head[1];i;i=e[i].nxt)
        ok[e[i].v]=dfs(e[i].v,1);
    for(int i=head[1];i;i=e[i].nxt) sort(dsr[e[i].v].begin(),dsr[e[i].v].end(),cmp);
    for(int i=head[1];i;i=e[i].nxt) {
        int v=e[i].v;
        if(!ok[v] && dsr[v].size()) {
            int x=mid-sum[dsr[v][dsr[v].size()-1]];
            if(e[i].q*2>=x) dsr[v].pop_back(),ok[v]=1;
        }
    }
    int cnt=0,gs=0;
    for(int i=head[1];i;i=e[i].nxt) {
        int v=e[i].v;
        for(int j=0;j<(int)dsr[v].size();++j)
            nb[++cnt]=mid-sum[dsr[v][j]];
        if(!ok[v]) cb[++gs]=e[i].q;
    }
    sort(nb+1,nb+1+cnt,greater<int>());
    sort(cb+1,cb+1+gs,greater<int>());
    if(cnt<gs) return 0;
    for(int i=1;i<=gs;++i)
        if(cb[i]>nb[i]) return 0;
    return 1;
}
int main() {
    n=read();
    ll l=0,r=0,ans=-1;
    for(int i=1;i<n;++i) {
        int u=read(),v=read(),w=read();
        add(u,v,w),add(v,u,w);r+=w;
    }
    m=read();
    for(int i=1;i<=m;++i) pos[i]=read();
    init(1,0,0);
    sum[0]=sum[1]=-oo;
    for(int j=1;j<=15;++j)
        for(int i=1;i<=n;++i)
            fa[i][j]=fa[fa[i][j-1]][j-1];
    while(l<=r) {
        ll mid=(l+r)>>1;
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<"\n";
    return 0;
}

原文地址:https://www.cnblogs.com/dsrdsr/p/11685480.html

时间: 2024-07-30 02:15:51

luogu P1084疫情控制 二分的相关文章

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

题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$小时内不能够走到根节点的子节点上的军队,让他们尽量往上走即可,走到哪里是哪里,这样显然不会更劣. 对于那些在$x$小时内能走到根节点的子节点上的军队,就让他们先走到根节点的子节点上. 然后搞搞贪心即可. #include<iostream> #include<cstdio> #incl

[luogu]P1084 疫情控制

原题链接:P1084 疫情控制 题意 给定一棵带权树,$1$号点为根节点,某些点上有军队. 现在要求移动这些军队,使军队覆盖所有的叶子节点,求移动距离最大值的最小值. 分析 很难直接求出最小值,我们可以考虑二分这个最小值,让原问题转化为判定问题. 二分最小值,我们只需要判断能否在$mid$距离内使军队全部移动到覆盖所有的叶子点. 1.上移军队 一个军队往哪个方向移动贡献最大? 明显是往根节点方向移动. 所以很明显我们第一步就是要把所有的节点尽可能地往上移动. 如果移动到顶(处于根节点的儿子节点)

洛谷 P1084 疫情控制 【二分+数据结构】

题目: H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境 城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是, 首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城市

洛谷P1084 疫情控制

题目:https://www.luogu.org/problemnew/show/P1084 这道题由于洛谷数据有点水,如果有vijos的推荐去vijos交一下,他的数据还好. vijos:https://vijos.org/p/1783 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立

[NOIP2012] 提高组 洛谷P1084 疫情控制

题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境 城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是, 首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城

P1084 疫情控制

题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城市间移动

NOIP2012 洛谷P1084 疫情控制

Description: H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路

洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从 首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以

习题:疫情控制(二分+倍增+贪心)

noip2012疫情控制 描述H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城市间移动,