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


    P1084 疫情控制

    题目描述

    H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。

    H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从 首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。

    现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在 一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。

    请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

    输入输出格式

    输入格式:

    第一行一个整数 n,表示城市个数。

    接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。

    接下来一行一个整数 m,表示军队个数。

    接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎的城市的编号。

    输出格式:

    共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。

    输入输出样例

    输入样例#1:
    4 
    1 2 1 
    1 3 2 
    3 4 3 
    2 
    2 2
    输出样例#1:
    3

    说明

    【输入输出样例说明】

    第一支军队在 2 号点设立检查点,第二支军队从 2 号点移动到 3 号点设立检查点,所需时间为 3 个小时。

    【数据范围】

    保证军队不会驻扎在首都。

    对于 20%的数据,2≤ n≤ 10;

    对于 40%的数据,2 ≤n≤50,0<w <10^5;

    对于 60%的数据,2 ≤ n≤1000,0<w <10^6;

    对于 80%的数据,2 ≤ n≤10,000;

    对于 100%的数据,2≤m≤n≤50,000,0<w <10^9。

    NOIP 2012 提高组 第二天 第三题

    【题解】

    倍增写反了调了半天。。

    各种细节

    写一下能想到的几点;

    1、倍增写反了 淦

    2、往根节点跳,跳不到就留下。跳上去回不来,如果那个点没有留下的,就留下;如果有留下的,就比较

    剩余值的大小,小的留下。为什么回不去,且那个点没有留下的,就要留下?因为这个点回不去,一定需要

    其他点填补,其他点剩余值比这个点大,不如让其他点做更大的事情

    代码比较乱

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <algorithm>
      6 
      7 const long long MAXN = 50000 + 10;
      8 const long long MAXM = 50000 + 10;
      9 
     10 inline void read(long long &x)
     11 {
     12     x = 0;char ch = getchar(), c = ch;
     13     while(ch < '0' || ch > '9')c = ch, ch = getchar();
     14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
     15     if(c == '-')x = -x;
     16 }
     17 
     18 struct Edge
     19 {
     20     long long u,v,next,w;
     21     Edge(long long _u, long long _v, long long _w, long long _next){u = _u;v = _v;w = _w;next = _next;}
     22     Edge(){}
     23 }edge[MAXN << 1];
     24 long long head[MAXN], cnt;
     25 
     26 inline void insert(long long a, long long b, long long c)
     27 {
     28     edge[++cnt] = Edge(a, b, c, head[a]);
     29     head[a] = cnt;
     30 }
     31 
     32 long long rank[MAXN],n,m,l,r,mid,fa[MAXN],have[MAXN],ans,have2[MAXN];
     33 
     34 long long b[MAXN],p[20][MAXN],len[20][MAXN],deep[MAXN];
     35 
     36 void dfs(long long u)
     37 {
     38     b[u] = 1;
     39     for(register long long pos = head[u];pos;pos = edge[pos].next)
     40     {
     41         long long v = edge[pos].v;
     42         if(b[v]) continue;
     43         fa[v] = u;
     44         deep[v] = deep[u] + 1;
     45         p[0][v] = u, len[0][v] = edge[pos].w;
     46         dfs(v);
     47     }
     48 }
     49 long long M = 0;
     50 
     51 void yuchuli()
     52 {
     53     while((1 << M) <= n) ++ M;
     54     -- M;
     55 
     56     for(register long long j = 1;j <= M;++ j)
     57         for(register long long i = 1;i <= n;++ i)
     58             p[j][i] = p[j - 1][p[j - 1][i]];
     59     for(register long long j = 1;j <= M;++j)
     60         for(register long long i = 1;i <= n;++ i)
     61             len[j][i] = len[j - 1][i] + len[j - 1][p[j - 1][i]];
     62 }
     63 
     64 long long dfs2(long long u)
     65 {
     66     if(have2[u])return 1;
     67     long long flag = 0;
     68     for(register long long pos = head[u];pos;pos = edge[pos].next)
     69     {
     70         long long v = edge[pos].v;
     71         if(fa[u] == v)continue;
     72         flag = dfs2(v);
     73         if(!flag)return 0;
     74     }
     75     return flag;
     76 }
     77 
     78 long long node1[MAXN], tot;
     79 
     80 long long tot2, mi[MAXN];
     81 
     82 struct TT
     83 {
     84     int re, rank;
     85     TT(int _re, int _rank){re = _re;rank = _rank;}    
     86     TT(){}
     87 }tt[MAXN];
     88 
     89 bool cmpp(TT a, TT b)
     90 {
     91     return a.re < b.re;
     92 }
     93 
     94 long long check(long long ma)
     95 {
     96     memset(tt, 0, sizeof(tt));
     97     memset(have2, 0, sizeof(have2));
     98     memset(mi, 0, sizeof(mi));
     99     tot2 = 0;
    100     
    101     for(register long long i = 1;i <= m;++ i)
    102     {
    103         long long now = rank[i], s = 0;
    104         if(now == 1)
    105         {
    106             tt[++tot2].re = ma;
    107             tt[tot2].rank = now;
    108             continue;
    109         }
    110         for(register long long j = M;j >= 0;-- j) 
    111             if(s + len[j][now] <= ma && p[j][now] > 1)
    112                 s += len[j][now], now = p[j][now];
    113         if(fa[now] == 1 && ma - s - len[0][now] > 0)
    114         {
    115             if(ma - s - len[0][now] < len[0][now]) 
    116             {
    117                 if(!mi[now]) mi[now] = ma - s - len[0][now], have2[now] = 1;
    118                 else if(mi[now] > ma - s - len[0][now])tt[++tot2].re = mi[now], mi[now] = ma - s - len[0][now], tt[tot2].rank = now;
    119                 else tt[++tot2].re = ma - s - len[0][now], tt[tot2].rank = now;
    120             }
    121             else tt[++tot2].re = ma - s - len[0][now], tt[tot2].rank = now;
    122         } 
    123         else ++ have2[now], mi[now] = ma - s - len[0][now];
    124     }
    125     for(register int i = 2;i <= n;++ i)
    126     {
    127         int tmp = have2[i];
    128         -- have2[i];
    129         if(fa[i] == 1 && dfs2(i) && mi[i] > 0)
    130         {
    131             tt[++tot2].re = mi[i]; tt[tot2].rank = i;
    132             -- tmp;
    133         }
    134         have2[i] = tmp;
    135     }
    136     std::sort(tt + 1, tt + 1 + tot2, cmpp);
    137     long long now = 1;
    138     for(register long long i = 1;i <= tot;++ i)
    139     {
    140         if(!dfs2(node1[i]))
    141         {
    142             if(now > tot2)return 0; 
    143             while(tt[now].re < len[0][node1[i]] && now <= tot2)++ now;
    144             if(now > tot2)return 0; 
    145             ++ now;
    146         }
    147     }
    148     return 1;
    149 }
    150 
    151 bool cmp(long long a, long long b)
    152 {
    153     return len[0][a] < len[0][b];
    154 } 
    155 
    156 int main()
    157 {
    158     read(n);
    159     register long long tmp1, tmp2, tmp3;
    160     for(register long long i = 1;i < n;++i)
    161     {
    162         read(tmp1), read(tmp2), read(tmp3);
    163         insert(tmp1, tmp2, tmp3);
    164         insert(tmp2, tmp1, tmp3);
    165         r += tmp3;
    166     }
    167     read(m);
    168     for(register long long j = 1;j <= m;++j)
    169         read(rank[j]), have[rank[j]] = 1;
    170     deep[1] = 1;
    171     dfs(1);
    172     for(register long long pos = head[1];pos;pos = edge[pos].next)
    173     {
    174         long long v = edge[pos].v;
    175         if(v != 1) node1[++tot] = v;
    176     }
    177     yuchuli();
    178     std::sort(node1 + 1, node1 + 1 + tot, cmp);
    179     l = 1;
    180     while(l <= r)
    181     {
    182         mid = (l + r) >> 1;
    183         if(check(mid)) ans = mid, r = mid - 1;
    184         else l = mid + 1;
    185     }
    186     if(!ans)
    187     {
    188         printf("-1");
    189         return 0;
    190     }
    191     if(check(0))ans = 0;
    192     printf("%lld", ans); 
    193     return 0;
    194 }
    NOIP2012Day2T3疫情控制
  • 相关阅读:
    2020CCPC秦皇岛 K 【Kindom's Power】(树上贪心dp)
    对于树上状态机dp问题的一些总结与思考
    PTA_L3题解集
    PTA_L2题解集
    树上dp_学习笔记
    2020牛客国庆集训派对day2 B【Cheap Delivers】(最短路+状压dp)
    2020牛客国庆集训派对day1
    Codeforces 1426F【Number of Subsequences】(dp)
    2019icpc陕西省赛
    CF1281E【Jeremy Bearimy】(树上点对最大值/最小值和)
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7526570.html
Copyright © 2020-2023  润新知