其实这道题不难
首先假设 1 1 1 是根节点
我看到这道题第一反应就是直接假设整棵树权值之和是某一个定值,然后再dfs造每一个 a x a_x ax 。(其实到这里就可以a了,但是不优雅)
我们发现,由于去掉某一个节点之后,它所有的儿子所在的子树之和都和它上面那一部分之和是一样的,于是我们就有了: s u m x ′ s s o n = s u m 1 − s u m x sum_{x's\ son}=sum_1-sum_x sumx′s son=sum1−sumx 其中( x ≠ 1 x\ne1 x=1,下同)
又因为: a x = s u m x − ∑ s u m x ′ s s o n a_x=sum_x-\sum sum_{x's\ son} ax=sumx−∑sumx′s son
结合一下就成了 a x = s u m 1 − d e g x × ( s u m 1 − s u m x ) a_x=sum_1-deg_x\times(sum_1-sum_x) ax=sum1−degx×(sum1−sumx)
当我们令 s u m 1 = 0 sum_1=0 sum1=0 时,发现:
- s u m x ′ s s o n = − s u m x sum_{x's\ son}=-sum_x sumx′s son=−sumx
- a x = d e g x ∗ s u m x a_x=deg_x*sum_x ax=degx∗sumx
我们再令 s u m x = ( − 1 ) d e p x sum_x=(-1)^{dep_x} sumx=(−1)depx ,就可以发现 a x = d e g x ( − 1 ) d e p x a_x=deg_x(-1)^{dep_x} ax=degx(−1)depx
不难发现,这个结论在 x = 1 x=1 x=1 时也成立
再手动构造几组小数据后发现构造方法正确,就可以优雅的写代码了,芜湖起飞!
最后献上我其丑无比的代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,ans[N];
vector<int>ed[N];
void dfs(int x,int fa,int k){
ans[x]=ed[x].size()*k;
for(int y:ed[x])if(fa!=y)dfs(y,x,-k);
}
void solve(){
cin>>n;
for(int i=1;i<=n;i++)ed[i].clear();
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
ed[u].emplace_back(v);
ed[v].emplace_back(u);
}
dfs(1,1,1);
for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
cout<<'\n';
}
int main(){
int t;
cin>>t;
while(t--)solve();
}