zoukankan      html  css  js  c++  java
  • NOIP2012 疫情控制

    题目描述 Description

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

    也是树中的根节点。

    H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境

    城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境

    城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,

    首都是不能建立检查点的。

    现在,在 H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军

    队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在

    一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等

    于道路的长度(单位:小时)。

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

    输入描述 Input Description

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

    接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从

    城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。

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

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

    的城市的编号。

    输出描述 Output Description

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

    样例输入 Sample Input

    1 2 1 

    1 3 2 

    3 4 3 

    2 2 

    样例输出 Sample Output

    3

    数据范围及提示 Data Size & Hint

    【输入输出样例说明】

    第一支军队在 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。

    //copy
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int maxn = 100000;
    typedef long long LL;
    multiset<int> S;
    multiset<int>::iterator it;
    int n,u,v,w,m,nownode;
    LL f[maxn][20];
    int y[maxn];
    int g[maxn][20];
    int sonTree[maxn];
    int cnt[maxn];
    int p[maxn];
    int Min[maxn]; 
    bool Leaf[maxn];
    bool son[maxn];
    struct    Arm
    {
              int opt,time;
    }A[maxn]; 
    struct    Graph
    {
         int node[maxn * 2], len[maxn * 2], next[maxn * 2], v[maxn * 2];
         int en;
         Graph(){ 
            memset(v,0,sizeof(v));
            memset(next,0, sizeof(next));
            memset(len,0,sizeof(len));  
            en  = 0; 
         }
         void   addEdge(int a,int b,int c)
         {
                en++; node[en] = b; len[en] = c; next[en] = v[a]; v[a] = en;
                en++; node[en] = a; len[en] = c; next[en] = v[b]; v[b] = en;
         }
    }G;
    void     DFS(int x,int father)
    {
             sonTree[x] = nownode;
             bool flag= true;
             for (int j = G.v[x]; j; j = G.next[j])
             {
                 if (G.node[j] != father)
                 {
                     //father[j] = x;
                     flag = false;
                     f[G.node[j]][0] = G.len[j];
                     g[G.node[j]][0] = x;
                     if (x==1) nownode = G.node[j];
                     DFS(G.node[j],x); 
                 }
             }
             Leaf[x] = flag;
    }
    void     find_leaf(int x, int father)
    {
             if (cnt[x]>0) return ;
             if (Leaf[x])
             {
                 son[nownode] = true;
                 return;
             }
             for (int j = G.v[x]; j ; j = G.next[j])
             {
                 if (G.node[j] != father)
                 {
                     if (x==1) nownode = G.node[j];
                     find_leaf(G.node[j], x);
                 }
             }
    }
    bool     ok(LL value)
    {
        S.clear();
        int arm = 0;
        memset(cnt,0,sizeof(cnt));
        memset(son,0,sizeof(son));
        for (int i = 1; i <= m ;++i)
        {
            int len = value;
            int Pos = p[i];
            for (int j = 16; j>=0; --j)
                {
                     if (f[Pos][j]<=len && g[Pos][j]!=0)
                     {
                         len-=f[Pos][j];
                         Pos =g[Pos][j];              
                     }
                }
            if (Pos == 1)
            {
                A[arm].opt = p[i];
                A[arm++].time  = len;
            } else
              cnt[Pos]++;
        }           
        find_leaf(1,0); 
        for (int i = 1;i <= n;++i) Min[i]= -1;
        for (int i = 0; i < arm ; ++ i)
        {
            if (son[sonTree[A[i].opt]])
            {
               if  (Min[sonTree[A[i].opt]] ==-1 || 
                  A[Min[sonTree[A[i].opt]]].time > A[i].time)
                    Min[sonTree[A[i].opt]] = i;
            }
        } 
        int tot = 0;
        for (int i = 1; i <= n;++i)
        {
            if (son[i] && Min[i] != -1 && A[Min[i]].time<f[i][0])
            {
                A[Min[i]].time = -1;       
            }else
            if (son[i]) y[tot++] = f[i][0];
        }
        sort(y,y+tot);
        for (int i = 0; i < arm;++i)
        if (A[i].time != -1)
            S.insert(A[i].time);
            
        for (int i = tot-1; i>=0; --i)
        {
            if (S.lower_bound(y[i]) == S.end()) return false;
            it = S.lower_bound(y[i]);
            S.erase(it);
        }
        return true;
    }
    int main()
    {
        cin>>n;
        for (int i = 1;i < n;++ i)
        {
            scanf("%d %d %d",&u,&v,&w);
            G.addEdge(u,v,w);
        }
        cin>>m ;
        for (int i = 1;i <= m;++i)
        {
            scanf("%d", &p[i]);
            // cnt[p[i]] ++;
        }
        DFS(1,0);
        /*for (int i = 1;i <= n; ++i)
        {
            cout <<i<<" "<<f[i][0]<<" "<<g[i][0] << endl; 
        }*/
        for (int i = 1; i <=16; ++i)
            for (int j = 1; j <= n ;++j)
            {
                f[j][i] = f[j][i-1]+ f[g[j][i-1]][i-1];
                g[j][i] = g[g[j][i-1]][i-1];
            }
        
        
        LL L = 0 , R = (LL)n * round(10e9);
        int ans = -1;
        while (L <= R)
        {
              LL mid = (L+R) /2;
              if (ok(mid)) R = mid-1, ans = mid; 
              else L = mid+1;
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    pch”预编译头文件来自编译器的其他版本,或者预编译头为 C++ 而在 C 中使用它(或相反) and vs找不到路径
    VC++获得当前系统时间的几种方案
    无法解析的外部符号 __imp____glutInitWithExit@12,该符号在函数 _glutInit_ATEXIT_HACK@8 中被引用
    error C2381: “exit” : 重定义
    vs2019 link glaux.lib 无法解析的外部符号,是缺少一个Lib
    操作系统算法整理+汇总
    vs2019配置glm包
    第二题 既约分数
    死磕Spring之IoC篇
    精尽Spring Boot源码分析
  • 原文地址:https://www.cnblogs.com/hyfer/p/5852507.html
Copyright © 2011-2022 走看看