zoukankan      html  css  js  c++  java
  • BZOJ3611 HEOI2014大工程

    先建虚树,然后统计答案。

    对于这个两点间最大值和最小值的操作我参考了hzwer的代码。

    建虚树时注意判自环

    By:大奕哥

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=1e6+10;
      4 struct node{
      5     int to,nex,w;
      6 }e[N<<1],d[N<<1];
      7 int cnt,dnt,dead[N],head[N],ans1,ans2,id,idx[N],h[N],f[N][21],dd[N],q,n,top,size[N];
      8 bool v[N];long long sum;
      9 void add(int x,int y,int w)
     10 {
     11     e[++cnt].to=y;e[cnt].w=w;e[cnt].nex=head[x];head[x]=cnt;
     12 }
     13 void ddd(int x,int y,int w)
     14 {
     15     if(x==y)return;
     16     d[++dnt].to=y;d[dnt].w=w;d[dnt].nex=dead[x];dead[x]=dnt;
     17 }
     18 void dfs(int x,int fa)
     19 {
     20     for(int i=1;i<=20;++i)
     21     f[x][i]=f[f[x][i-1]][i-1];
     22     idx[x]=++id;
     23     for(int i=head[x];i;i=e[i].nex)
     24     {
     25         int y=e[i].to;
     26         if(y==fa)continue;
     27         f[y][0]=x;dd[y]=dd[x]+1;
     28         dfs(y,x);
     29     }
     30 }
     31 int lca(int x,int y)
     32 {
     33     if(dd[x]<dd[y])swap(x,y);
     34     int tmp=dd[x]-dd[y];
     35     for(int i=0;i<=20;++i)
     36     if(tmp&(1<<i))x=f[x][i];
     37     for(int i=20;i>=0;--i)
     38     if(f[x][i]!=f[y][i])
     39     x=f[x][i],y=f[y][i];
     40     return x==y?x:f[x][0];
     41 }
     42 long long dp[N];
     43 int mx[N],mn[N],k,s[N];
     44 void donggui(int x)
     45 {
     46     size[x]=v[x];dp[x]=0;
     47     mn[x]=v[x]?0:2e9;
     48     mx[x]=v[x]?0:-2e9;
     49     for(int i=dead[x];i;i=d[i].nex)
     50     {
     51         int y=d[i].to;
     52         donggui(y);
     53         sum+=1ll*(dp[x]+1ll*size[x]*d[i].w)*size[y]+1ll*dp[y]*size[x];
     54         size[x]+=size[y];
     55         dp[x]+=dp[y]+1ll*size[y]*d[i].w;
     56         ans1=min(ans1,mn[x]+d[i].w+mn[y]);
     57         ans2=max(ans2,mx[x]+d[i].w+mx[y]);
     58         mn[x]=min(mn[x],mn[y]+d[i].w);
     59         mx[x]=max(mx[x],mx[y]+d[i].w);
     60     }
     61     dead[x]=0;
     62 }
     63 bool cmp(int x,int y)
     64 {
     65     return idx[x]<idx[y];
     66 }
     67 void solve()
     68 {
     69     scanf("%d",&k);
     70     for(int i=1;i<=k;++i)scanf("%d",&h[i]);
     71     for(int i=1;i<=k;++i)v[h[i]]=1;
     72     sort(h+1,h+1+k,cmp);
     73     top=dnt=0;
     74     s[++top]=1;
     75     for(int i=1;i<=k;++i)
     76     {
     77         int x=h[i];int ff=lca(x,s[top]);
     78         if(ff==s[top]){s[++top]=x;continue;}
     79         while(ff==lca(s[top-1],x))
     80         {
     81             ddd(s[top-1],s[top],dd[s[top]]-dd[s[top-1]]);
     82             top--;ff=lca(s[top],x);
     83         }
     84         ddd(ff,s[top],dd[s[top]]-dd[ff]);
     85         s[top]=ff;s[++top]=x;
     86     }
     87     for(int i=1;i<top;++i)
     88     ddd(s[i],s[i+1],dd[s[i+1]]-dd[s[i]]);
     89     ans1=2e9;ans2=-2e9;sum=0;
     90     donggui(1);
     91     printf("%lld %d %d
    ",sum,ans1,ans2);
     92     for(int i=1;i<=k;++i)v[h[i]]=0;
     93     return;
     94 }
     95 int main()
     96 {
     97     scanf("%d",&n);
     98     for(int i=1;i<n;++i)
     99     {
    100         int x,y;
    101         scanf("%d%d",&x,&y);
    102         add(x,y,1);add(y,x,1);
    103     }
    104     dfs(1,0);
    105     scanf("%d",&q);
    106     while(q--)solve();
    107     return 0;
    108 }
  • 相关阅读:
    Light Bulb(三分)
    Turn the corner (三分)
    xmu1214: 购物
    Tempter of the Bone(dfs奇偶剪枝)
    Oh, my goddess(bfs)
    nyoj三个水杯(bfs)
    组合数(dfs)
    吝啬的国度(dfs+vector)
    Cube Stacking(并差集深度+结点个数)
    python之socketserver实现并发
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8433027.html
Copyright © 2011-2022 走看看