单(树上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
以上是关于单(树上DP+乱搞)的主要内容,如果未能解决你的问题,请参考以下文章
CF1363E Tree Shuffling(贪心+树上乱搞)