题解 [CF1656E] Equal Tree Sums
十分优美的解法,有被气震撼到
我先后尝试了使每个子树权值和均相等(无法处理度数为 2 的点)
固定一个度数为 1 的点权为 \(a\),及一个相邻点权为 \(b\),则其余点权均可以唯一表示为 \(k_1a+k_2b\) 的形式
然后发现可能解出 \(k_1=k_2=0\) 的情况(我先前认为它是不可能的)
于是康题解:
构造方法是将原树黑白染色
则每个点的权值为 \(\pm\deg(u)\),符号取决于颜色
证明是显然的:考虑删去一个点后每个子树的贡献一定为 \(\pm1\),符号与当前节点的颜色对应符号相反
复杂度 \(O(n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define ll long long
// #define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int head[N], cnt[N], col[N], ecnt;
struct edge{int to, next;}e[N<<1];
inline void add(int s, int t) {e[++ecnt]={t, head[s]}; head[s]=ecnt;}
void dfs(int u, int fa) {
for (int i=head[u]; ~i; i=e[i].next)
if (e[i].to!=fa) col[e[i].to]=col[u]*-1, dfs(e[i].to, u);
}
signed main()
{
int T=read();
while (T--) {
n=read(); ecnt=0;
for (int i=1; i<=n; ++i) head[i]=-1, cnt[i]=0;
for (int i=1,u,v; i<n; ++i) {
u=read(); v=read();
add(u, v); add(v, u);
++cnt[u]; ++cnt[v];
}
col[1]=1; dfs(1, 0);
for (int i=1; i<=n; ++i) printf("%d%c", col[i]*cnt[i], " \n"[i==n]);
}
return 0;
}