zoukankan      html  css  js  c++  java
  • bzoj 2286: [Sdoi2011消耗战

    虚树,,,,还是虚树2333

    虚树这个东西嘛,就把关键点拿出来,利用树链上有前缀和的性质,在不改变原来相对位置的情况下,添加尽量少的点,使关键点构成新的(虚)树。。

    (然而感觉虚树并不虚的,,我才虚啊。。)

    这个题虚树搞出来之后随便搞搞就行。。。

      1 #include <bits/stdc++.h>
      2 #define inf 0x7fffffff
      3 #define LL long long
      4 using namespace std;
      5 inline int ra()
      6 {
      7     int x=0,f=1; char ch=getchar();
      8     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
      9     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
     10     return x*f;
     11 }
     12 int bin[20];
     13 int n,m,cnt,ind,top;
     14 int head[250005],rehead[250005],fa[250005][20];
     15 LL mn[250005],f[250005];
     16 int h[250005],dfn[250005],deep[250005];
     17 int st[250005];
     18 struct edge{
     19     int to,next,v;
     20 }e[500005],re[500005];
     21 void insert(int x, int y, int v){
     22     e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt; e[cnt].v=v;
     23 }
     24 void insert2(int x, int y)
     25 {
     26     if (x==y) return;
     27     re[++cnt].to=y; re[cnt].next=rehead[x]; rehead[x]=cnt;
     28 }
     29 void pre(int x)
     30 {
     31     dfn[x]=++ind;
     32     for (int i=1; bin[i]<=deep[x]; i++)
     33         fa[x][i]=fa[fa[x][i-1]][i-1];
     34     for (int i=head[x];i;i=e[i].next)
     35     {
     36         if (e[i].to==fa[x][0]) continue;
     37         fa[e[i].to][0]=x;
     38         mn[e[i].to]=min(mn[x],(LL)e[i].v);
     39         deep[e[i].to]=deep[x]+1;
     40         pre(e[i].to);
     41     }
     42 }
     43 int lca(int x, int y)
     44 {
     45     if (deep[x]<deep[y]) swap(x,y);
     46     int t=deep[x]-deep[y];
     47     for (int i=0; (1<<i)<=t; i++)
     48         if ((1<<i)&t) x=fa[x][i];
     49     for (int i=19; i>=0; i--)
     50         if (fa[x][i]!=fa[y][i])
     51             x=fa[x][i],y=fa[y][i];
     52     if (x==y) return x;
     53     return fa[x][0];
     54 }
     55 void dp(int x)
     56 {
     57     f[x]=mn[x];
     58     LL tmp=0;
     59     for (int i=rehead[x]; i; i=re[i].next)
     60     {
     61         dp(re[i].to); tmp+=f[re[i].to];
     62     }
     63     rehead[x]=0;
     64     if (tmp==0) f[x]=mn[x];
     65     else if (tmp<=f[x]) f[x]=tmp;
     66 }
     67 bool cmp(int a, int b){return dfn[a]<dfn[b];}
     68 void solve()
     69 {
     70     int K=ra(); cnt=0;
     71     for (int i=1; i<=K; i++) h[i]=ra();
     72     sort(h+1,h+K+1,cmp);
     73     int tot=0; h[++tot]=h[1];
     74     for (int i=2; i<=K; i++)
     75         if (lca(h[tot],h[i])!=h[tot]) h[++tot]=h[i];
     76     st[++top]=1;
     77     for (int i=1; i<=tot; i++)
     78     {
     79         int now=h[i],f=lca(now,st[top]);
     80         while (1)
     81         {
     82             if (deep[f]>=deep[st[top-1]])
     83             {
     84                 insert2(f,st[top--]);
     85                 if (st[top]!=f) st[++top]=f;
     86                 break;
     87             }
     88             insert2(st[top-1],st[top]); top--;
     89         }
     90         if (st[top]!=now) st[++top]=now;
     91     }
     92     while (--top) insert2(st[top],st[top+1]);
     93     dp(1);
     94     printf("%lld
    ",f[1]);
     95 }
     96 int main(int argc, char const *argv[])
     97 {
     98     bin[0]=1; for (int i=1; i<=20; i++) bin[i]=bin[i-1]<<1;
     99     n=ra();
    100     for (int i=1; i<n; i++)
    101     {
    102         int x=ra(),y=ra(); int v=ra();
    103         insert(x,y,v); insert(y,x,v);
    104     }
    105     mn[1]=1e60; pre(1); m=ra();
    106     for (int i=1; i<=m; i++) solve();
    107     return 0;
    108 }
  • 相关阅读:
    2021软件工程-个人阅读作业
    OO第四单元——基于UML的UML解析器总结&OO课程总结
    OO第三单元——基于JML的社交网络总结
    OO第二单元——电梯作业总结
    SQL拼接字符串
    SQL查询列表中每种类型的第一条
    JS获取当前时间,设置不可用以前的时间
    JavaScript中的函数使用
    .Net软件开发面试技巧
    .Net小白的第一篇博客
  • 原文地址:https://www.cnblogs.com/ccd2333/p/6512000.html
Copyright © 2011-2022 走看看