• BZOJ 3611: [Heoi2014]大工程


    3611: [Heoi2014]大工程

    Time Limit: 60 Sec  Memory Limit: 512 MB
    Submit: 1101  Solved: 478
    [Submit][Status][Discuss]

    Description

    国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。 
    我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。 
    在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
     现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
    现在对于每个计划,我们想知道:
     1.这些新通道的代价和
     2.这些新通道中代价最小的是多少 
    3.这些新通道中代价最大的是多少
     

    Input

    第一行 n 表示点数。

     接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
    点从 1 开始标号。 接下来一行 q 表示计划数。
    对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
     第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。
     

    Output

    输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。 

     

    Sample Input

    10
    2 1
    3 2
    4 1
    5 2
    6 4
    7 5
    8 6
    9 7
    10 9
    5
    2
    5 4
    2
    10 4
    2
    5 2
    2
    6 1
    2
    6 1

    Sample Output

    3 3 3
    6 6 6
    1 1 1
    2 2 2
    2 2 2

    HINT

    n<=1000000 


    q<=50000并且保证所有k之和<=2*n 

    Source

    [Submit][Status][Discuss]

    建出虚树,树形DP

      1 #include <bits/stdc++.h>
      2 
      3 namespace scanner
      4 {
      5     inline char nextChar(void)
      6     {
      7         static const int siz = 1 << 20;
      8         
      9         static char buf[siz];
     10         static char *hd = buf + siz;
     11         static char *tl = buf + siz;
     12         
     13         if (hd == tl)
     14             fread(hd = buf, 1, siz, stdin);
     15         
     16         return *hd++;
     17     }
     18     
     19     inline int nextInt(void)
     20     {
     21         register int ret = 0;
     22         register bool neg = false;
     23         register char bit = nextChar();
     24         
     25         for (; bit < 48; bit = nextChar())
     26             if (bit == '-')neg ^= true;
     27         
     28         for (; bit > 47; bit = nextChar())
     29             ret = ret * 10 + bit - '0';
     30         
     31         return neg ? -ret : ret;
     32     }
     33 }
     34 
     35 const int inf = 1e9;
     36 
     37 const int maxn = 2000005;
     38 const int maxm = 5000005;
     39 
     40 struct graph
     41 {
     42     int hd[maxn], to[maxm], nt[maxm], tot;
     43     
     44     inline graph(void)
     45     {
     46         tot = top = 0;
     47         memset(hd, 0, sizeof(hd));
     48         memset(marked, 0, sizeof(marked));
     49     }
     50     
     51     inline void addEdge(int x, int y)
     52     {
     53         nt[++tot] = hd[x]; to[tot] = y; hd[x] = tot;
     54         nt[++tot] = hd[y]; to[tot] = x; hd[y] = tot;
     55         
     56         markPoint(x);
     57         markPoint(y);
     58     }
     59     
     60     int used[maxn], marked[maxn], top;
     61     
     62     inline void markPoint(int t)
     63     {
     64         if (!marked[t])used[++top] = t, marked[t] = true;
     65     }
     66     
     67     inline void recovery(void)
     68     {
     69         while (top)
     70         {
     71             int t = used[top--];
     72             marked[t] = false;
     73             hd[t] = 0;
     74         }
     75     }
     76 };
     77 
     78 struct boolean
     79 {
     80     bool s[maxn];
     81     
     82     inline boolean(void)
     83     {
     84         top = 0;
     85         memset(s, 0, sizeof(s));
     86         memset(marked, 0, sizeof(marked));
     87     }
     88     
     89     inline void mark(int t)
     90     {
     91         s[t] = true;
     92         
     93         markPoint(t);
     94     }
     95     
     96     int used[maxn], marked[maxn], top;
     97     
     98     inline void markPoint(int t)
     99     {
    100         if (!marked[t])used[++top] = t, marked[t] = true;
    101     }
    102     
    103     inline void recovery(void)
    104     {
    105         while (top)
    106         {
    107             int t = used[top--];
    108             marked[t] = false;
    109             s[t] = false;
    110         }
    111     }
    112     
    113     inline bool operator [] (int t)
    114     {
    115         return s[t];
    116     }
    117 };
    118 
    119 int n, m;
    120 
    121 graph src;
    122 graph use;
    123 
    124 int dfn[maxn], dep[maxn], fa[maxn][21];
    125 
    126 void preworkDfs(graph &g, int u, int f)
    127 {
    128     static int tim = 0;
    129     
    130     dfn[u] = ++tim;
    131     dep[u] = dep[f] + 1;
    132     
    133     fa[u][0] = f;
    134     
    135     for (int i = 1; i <= 20; ++i)
    136         fa[u][i] = fa[fa[u][i - 1]][i - 1];
    137     
    138     for (int i = g.hd[u]; i; i = g.nt[i])
    139         if (f != g.to[i])preworkDfs(g, g.to[i], u);
    140 }
    141 
    142 inline int getLca(int a, int b)
    143 {
    144     if (dep[a] < dep[b])
    145         a ^= b ^= a ^= b;
    146     
    147     for (int i = 20; ~i; --i)
    148         if (dep[fa[a][i]] >= dep[b])
    149             a = fa[a][i];
    150     
    151     if (a == b)return a;
    152     
    153     for (int i = 20; ~i; --i)
    154         if (fa[a][i] != fa[b][i])
    155             a = fa[a][i],
    156             b = fa[b][i];
    157     
    158     return fa[a][0];
    159 }
    160 
    161 inline bool cmpDfn(int a, int b)
    162 {
    163     return dfn[a] < dfn[b];
    164 }
    165 
    166 boolean mrk;
    167 
    168 struct stack
    169 {
    170     int s[maxn], tot;
    171     
    172     inline void push(int t)
    173     {
    174         s[++tot] = t;
    175     }
    176     
    177     inline void pop(void)
    178     {
    179         if (tot)--tot;
    180     }
    181     
    182     inline int top(void)
    183     {
    184         return s[tot];
    185     }
    186     
    187     inline int tat(void)
    188     {
    189         return s[tot - 1];
    190     }
    191     
    192     inline int size(void)
    193     {
    194         return tot;
    195     }
    196     
    197     inline bool empty(void)
    198     {
    199         return tot == 0;
    200     }
    201     
    202     inline void clear(void)
    203     {
    204         tot = 0;
    205     }
    206 };
    207 
    208 stack stk;
    209 
    210 typedef long long lnt;
    211 
    212 struct answer
    213 {
    214     int maxi;
    215     int mini;
    216     
    217     inline void setup(void)
    218     {
    219         maxi = 0;
    220         mini = inf;
    221     }
    222     
    223     inline void updateMin(int t)
    224     {
    225         if (mini > t)
    226             mini = t;
    227     }
    228     
    229     inline void updateMax(int t)
    230     {
    231         if (maxi < t)
    232             maxi = t;
    233     }
    234 }ans;
    235 
    236 lnt all, dp[maxn], sz[maxn];
    237 
    238 int maxPath[maxn];
    239 int minPath[maxn];
    240 
    241 void getansDfs(graph &g, int u, int f)
    242 {
    243     dp[u] = 0LL;
    244     sz[u] = mrk[u];
    245     maxPath[u] = 0;
    246     minPath[u] = inf;
    247     
    248     for (int i = g.hd[u]; i; i = g.nt[i])
    249         if (g.to[i] != f)
    250         {
    251             int v = g.to[i];
    252             int d = dep[v] - dep[u];
    253             
    254             getansDfs(g, v, u);
    255             
    256             sz[u] += sz[v];
    257             dp[u] += dp[v];
    258             dp[u] += sz[v] * (all - sz[v]) * d;
    259             
    260             ans.updateMin(minPath[v] + minPath[u] + d);
    261             ans.updateMax(maxPath[v] + maxPath[u] + d);
    262             
    263             if (minPath[u] > minPath[v] + d)
    264                 minPath[u] = minPath[v] + d;
    265             
    266             if (maxPath[u] < maxPath[v] + d)
    267                 maxPath[u] = maxPath[v] + d;
    268         }
    269     
    270     if (mrk[u])
    271     {
    272         ans.updateMin(minPath[u]);
    273         ans.updateMax(maxPath[u]);
    274         
    275         minPath[u] = 0;
    276     }
    277 }
    278 
    279 signed main(void)
    280 {
    281     n = scanner::nextInt();
    282     
    283     for (int i = 1; i < n; ++i)
    284     {
    285         int x = scanner::nextInt();
    286         int y = scanner::nextInt();
    287         
    288         src.addEdge(x, y);
    289     }
    290     
    291     preworkDfs(src, 1, 0);
    292     
    293     m = scanner::nextInt();
    294     
    295     while (m--)
    296     {
    297         static int k, p[maxn];
    298         
    299         k = scanner::nextInt();
    300         
    301         for (int i = 1; i <= k; ++i)
    302             p[i] = scanner::nextInt();
    303         
    304         std::sort(p + 1, p + k + 1, cmpDfn);
    305         
    306         use.recovery();
    307         mrk.recovery();
    308         
    309         ans.setup();
    310         stk.clear();
    311         
    312         all = k;
    313         
    314         for (int i = 1; i <= k; ++i)
    315             mrk.mark(p[i]);
    316         
    317         for (int i = 1; i <= k; ++i)
    318         {
    319             if (!stk.empty())
    320             {
    321                 int t = getLca(p[i], stk.top());
    322                 
    323                 while (dfn[t] < dfn[stk.top()])
    324                 {
    325                     if (dfn[t] >= dfn[stk.tat()])
    326                     {
    327                         use.addEdge(t, stk.top()), stk.pop();
    328                         
    329                         if (stk.top() != t)
    330                             stk.push(t);
    331                         
    332                         break;
    333                     }
    334                     
    335                     use.addEdge(stk.top(), stk.tat()), stk.pop();
    336                 }
    337             }
    338                 
    339             stk.push(p[i]);
    340         }
    341         
    342         while (stk.size() > 1)
    343             use.addEdge(stk.top(), stk.tat()), stk.pop();
    344         
    345         getansDfs(use, stk.top(), 0);
    346         
    347         printf("%lld %d %d
    ", dp[stk.top()], ans.mini, ans.maxi);
    348     }
    349 }

    @Author: YouSiki

  • 相关阅读:
    python中装饰器的原理
    python中封装、继承、多态
    Linux 中数组的使用
    Linux中环境变量中文件执行顺序
    Linux中FTP的一点理解
    原来... 拷贝构造函数的参数为什么必须使用引用类型
    C++ Programming language读书笔记
    linux 用户态 内核态
    Linux命令学习整理。
    fork &vfork --陈皓
  • 原文地址:https://www.cnblogs.com/yousiki/p/6298480.html
Copyright © 2020-2023  润新知