单(树上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

猜你喜欢

转载自www.cnblogs.com/toot-wjh/p/11261786.html