单(树上DP+乱搞)

Posted toot-wjh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单(树上DP+乱搞)相关的知识,希望对你有一定的参考价值。

单(single):

  题干

  题解:

    t=0时,考虑DP,我们可推出树结点与子结点b数组的关系,

          $ b[x]=b[fa]-sum[i]+tot-sum[i]\\\\b[i]=b[fa]+tot-2*sum[i] $

    显然我们可两次$dfs$求解。

    t=1时,由上式得,$ b[i]-b[fa]=tot-sum[i]*2 (i!=root) $

    累加得:$ \\sum\\limits_i!=root^n(b[i]-b[fa])=tot*(n-1)-\\sum\\limits_i!=root^n sum[i] $

    而右面的式子恰为:$ b[root]=\\sum\\limits_i^n sum[i] $

    代入可得:$ \\sum\\limits_i!=root^n(b[i]-b[fa])+2*b[root]=tot*(n-1) $

    于是我们可以用$dfs$求出$tot$,再$dfs$求出$sum$数组和$a$数组。

  code:

技术图片
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<queue>
  6 #include<algorithm>
  7 using namespace std;
  8 #define R register
  9 #define int long long
 10 #define ll long long
 11 inline ll read()
 12     ll aa=0;R int bb=1;char cc=getchar();
 13     while(cc<0||cc>9)
 14         if(cc==-)bb=-1;cc=getchar();
 15     while(cc>=0&&cc<=9)
 16         aa=(aa<<1)+(aa<<3)+(cc^48);cc=getchar();
 17     return aa*bb;
 18 
 19 const int N=100010;
 20 struct edge
 21     int v,last;
 22 ed[N*2];
 23 int first[N],tot;
 24 inline void add(int x,int y)
 25 
 26     ed[++tot].v=y;
 27     ed[tot].last=first[x];
 28     first[x]=tot;
 29 
 30 int T,n,t,a[N],b[N];
 31 int sum[N],siz[N],num;
 32 void dfsi(int x,int fa)
 33 
 34     sum[x]=0;siz[x]=a[x];
 35     for(R int i=first[x],v;i;i=ed[i].last)
 36         v=ed[i].v;
 37         if(v==fa)continue;
 38         dfsi(v,x);
 39         siz[x]+=siz[v];
 40         sum[x]+=sum[v]+siz[v];
 41     
 42     return;
 43 
 44 void dfsj(int x,int fa)
 45 
 46     if(x!=1)
 47         b[x]=b[fa]-2*siz[x]+siz[1];
 48     
 49     for(R int i=first[x],v;i;i=ed[i].last)
 50         v=ed[i].v;
 51         if(v==fa)continue;
 52         dfsj(v,x);
 53     
 54 
 55 void dfsk(int x,int fa)
 56 
 57     if(x==1)num+=2*b[x];
 58     else num+=b[x]-b[fa];
 59     for(R int i=first[x],v;i;i=ed[i].last)
 60         v=ed[i].v;
 61         if(v==fa)continue;
 62         dfsk(v,x);
 63     
 64 
 65 void dfsq(int x,int fa)
 66 
 67     if(x!=1)a[x]=sum[x]=(num-b[x]+b[fa])/2;
 68     for(R int i=first[x],v;i;i=ed[i].last)
 69         v=ed[i].v;
 70         if(v==fa)continue;
 71         dfsq(v,x);
 72         if(x!=1)a[x]-=sum[v];
 73     
 74     if(x!=1)a[1]-=a[x];
 75 
 76 inline void init()
 77 
 78     tot=num=0;
 79     memset(first,0,sizeof(first));
 80     memset(sum,0,sizeof(sum));
 81     memset(siz,0,sizeof(siz));
 82     memset(a,0,sizeof(a));
 83     memset(b,0,sizeof(b));
 84 
 85 signed main()
 86 
 87     //bin[0]=1;for(R int i=1;i<=19;++i)bin[i]=bin[i-1]<<1;
 88     T=read();
 89     while(T--)
 90         init(); n=read();
 91         for(R int i=1,x,y;i<n;++i)
 92             x=read();y=read();
 93             add(x,y);add(y,x);
 94         
 95         t=read();
 96         if(t==0)
 97             for(R int i=1;i<=n;++i)a[i]=read();
 98             dfsi(1,0);b[1]=sum[1];dfsj(1,0);
 99             for(R int i=1;i<=n;++i)printf("%lld ",b[i]);puts("");
100         
101         else if(t==1)
102             for(R int i=1;i<=n;++i)b[i]=read();
103             dfsk(1,0);num/=(n-1);a[1]=num;dfsq(1,0);
104             for(R int i=1;i<=n;++i)printf("%lld ",a[i]);puts("");
105         
106     
107     return 0;
108 
View Code

 

以上是关于单(树上DP+乱搞)的主要内容,如果未能解决你的问题,请参考以下文章

hdu66212019hdu多校4 线段树上乱搞

CF1363E Tree Shuffling(贪心+树上乱搞)

atcoderAll Your Paths are Different Lengths[arc102D](乱搞)

Codeforces 1077E (二分乱搞或者dp)

fzyjojP2931 乱搞

BZOJ-4692Beautiful Spacing 二分答案 + 乱搞(DP?)