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\n",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 }

 

posted @ 2017-03-06 21:13  ws_ccd  阅读(127)  评论(0编辑  收藏  举报