bzoj 3611: [Heoi2014]大工程

虚树,跪,貌似搞出虚树之后的DP挺好想的,然而蒟蒻还是虚的扒了题解,,

  1 #include <bits/stdc++.h>
  2 #define LL long long
  3 #define inf 0x3f3f3f3f
  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 LL tot;
 13 int bin[20];
 14 int n,K,top,cnt,q,ind,ans1,ans2;
 15 int head[1000005],rehead[1000005],v[1000005];
 16 int mx[1000005],mn[1000005];
 17 int fa[1000005][20],deep[1000005],dfn[1000005],st[1000005],h[1000005];
 18 LL size[1000005],f[1000005];
 19 struct edge{
 20     int to,next,v;
 21 }e[2000005],re[2000005];
 22 void insert2(int x, int y)
 23 {
 24     if (x==y) return;
 25     re[++cnt].next=rehead[x]; re[cnt].to=y; rehead[x]=cnt; re[cnt].v=deep[y]-deep[x];
 26 }
 27 void insert(int x, int y){e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt;}
 28 void pre_dfs(int x)
 29 {
 30     dfn[x]=++ind;
 31     for (int i=1; bin[i]<=deep[x]; i++)
 32             fa[x][i]=fa[fa[x][i-1]][i-1];
 33     for (int i=head[x];i;i=e[i].next)
 34     {
 35         if (e[i].to==fa[x][0]) continue;
 36         deep[e[i].to]=deep[x]+1;
 37         fa[e[i].to][0]=x;
 38         size[x]+=size[e[i].to];
 39         pre_dfs(e[i].to);
 40     }
 41 }
 42 int lca(int x, int y)
 43 {
 44     if (deep[x]<deep[y]) swap(x,y);
 45     int t=deep[x]-deep[y];
 46     for (int i=0; bin[i]<=t; i++)
 47         if (t&(1<<i)) x=fa[x][i];
 48     for (int i=18; i>=0; i--)
 49         if (fa[x][i]!=fa[y][i])
 50             x=fa[x][i],y=fa[y][i];
 51     return x==y?x:fa[x][0];
 52 }
 53 bool cmp(int a, int b){return dfn[a]<dfn[b];}
 54 void dp(int x)
 55 {
 56     size[x]=v[x]; f[x]=0;
 57     mn[x]=v[x]?0:inf;
 58     mx[x]=v[x]?0:-inf;
 59     for (int i=rehead[x];i;i=re[i].next)
 60     {
 61         dp(re[i].to);
 62         tot+=(f[x]+size[x]*re[i].v)*size[re[i].to]+f[re[i].to]*size[x];
 63         size[x]+=size[re[i].to];
 64         f[x]+=f[re[i].to]+size[re[i].to]*re[i].v;
 65         ans1=min(ans1,mn[x]+mn[re[i].to]+re[i].v);
 66         ans2=max(ans2,mx[x]+mx[re[i].to]+re[i].v);
 67         mn[x]=min(mn[x],mn[re[i].to]+re[i].v);
 68         mx[x]=max(mx[x],mx[re[i].to]+re[i].v);
 69     }
 70     rehead[x]=0;
 71 }
 72 void solve()
 73 {
 74     int K=ra();
 75     for (int i=1; i<=K; i++) v[h[i]=ra()]=1;
 76     sort(h+1,h+K+1,cmp);
 77     top=cnt=0;
 78     st[++top]=1;
 79     for (int i=1; i<=K; i++)
 80     {
 81         int x=h[i]; int f=lca(x,st[top]);
 82         if (f==st[top]) {st[++top]=x; continue;}
 83         while (f==lca(x,st[top-1]))
 84         {
 85             insert2(st[top-1],st[top]);
 86             top--; f=lca(x,st[top]);
 87         }
 88         insert2(f,st[top]); st[top]=f; st[++top]=x;
 89     }
 90     if (top) while (--top) insert2(st[top],st[top+1]);
 91     ans1=inf; ans2=-inf; tot=0; 
 92     dp(1);
 93     printf("%lld ",tot); printf("%d %d\n",ans1,ans2);
 94     for (int i=1; i<=K; i++) v[h[i]]=0;
 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();
103         insert(x,y); insert(y,x);
104     }
105     pre_dfs(1); 
106     int Q=ra();
107     for (int i=1; i<=Q; i++) solve();
108     return 0;
109 }

 

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