CodeTON Round 1 E. Equal Tree Sums


传送门

题目大意

一棵 \(n(3\leq n\leq 10^5)\) 个节点的无根树,为每个节点 \(i\) 赋予一个权值 \(a_i(-10^5\leq a_i\leq 10^5,a_i\neq 0)\) ,使得在删去任意一个节点后,剩下的各个连通块的权值和都相等。

思路

我们对这棵树做二分图染色,一部分的节点赋予 \(deg_v\) 的权值,另一部分的节点赋予 \(-deg_v\) 的权值,这样在删去某个顶点 \(u\) 后,连通块中所有不与 \(u\) 相连的边会为该连通块权值的总和贡献一个 \(1\) 和一个 \(-1\) ,总的贡献为 \(0\) ,而该连通块与 \(u\) 的连边对总和的贡献取决于 \(w_u\) 的正负性,于是删去 \(u\) 后各个连通块的权值和就都相等了。

代码

#include
#include
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair PII;
#define all(x) x.begin(),x.end()
//#define int LL
//#define lc p*2+1
//#define rc p*2+2
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const LL MOD = 100000000;
const LL mod = 998244353;
const int maxn = 200010;

vectorG[maxn];
int T, N;
int ans[maxn];

void add_edge(int from, int to)
{
	G[from].push_back(to);
	G[to].push_back(from);
}

void dfs(int v, int p, int t)
{
	if (!t)
		ans[v] = -ans[v];
	for (auto to : G[v])
	{
		if (to == p)
			continue;
		dfs(to, v, t ^ 1);
	}
}

void solve()
{
	dfs(1, 0, 0);
	for (int i = 1; i <= N; i++)
		cout << ans[i] << ' ';
	cout << endl;
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		cin >> N;
		for (int i = 1; i <= N; i++)
			G[i].clear(), ans[i] = 0;
		int u, v;
		for (int i = 1; i < N; i++)
		{
			cin >> u >> v;
			add_edge(u, v);
			ans[u]++, ans[v]++;
		}
		solve();
	}

	return 0;
}