[CF1844G] Tree Weights

题目描述

You are given a tree with $ n $ nodes labelled $ 1,2,\dots,n $ . The $ i $ -th edge connects nodes $ u_i $ and $ v_i $ and has an unknown positive integer weight $ w_i $ . To help you figure out these weights, you are also given the distance $ d_i $ between the nodes $ i $ and $ i+1 $ for all $ 1 \le i \le n-1 $ (the sum of the weights of the edges on the simple path between the nodes $ i $ and $ i+1 $ in the tree).

Find the weight of each edge. If there are multiple solutions, print any of them. If there are no weights $ w_i $ consistent with the information, print a single integer $ -1 $ .

输入格式

The first line contains a single integer $ n $ ( $ 2 \le n \le 10^5 $ ).

The $ i $ -th of the next $ n-1 $ lines contains two integers $ u_i $ and $ v_i $ ( $ 1 \le u_i,v_i \le n $ , $ u_i \ne v_i $ ).

The last line contains $ n-1 $ integers $ d_1,\dots,d_{n-1} $ ( $ 1 \le d_i \le 10^{12} $ ).

It is guaranteed that the given edges form a tree.

\(n-1\) 条边, \(n-1\) 个等式,理论上是可以暴力解方程的。复杂度 \(O(n^3)\)

钦定 1 为根的话,考虑从 \(1\) 到点 \(x\) 的距离入手,设为 \(a_x\)

方程形如 \(a_i+a_{i+1}-2a_d=s_{i}\),发现 \(a_d\) 很烦,想办法把他消掉。

由于 \(a_1\) 一定为 \(0\),所以将整个方程 \(\mod 2\) 可以得到 \(a_i\mod 2\) 的值。

然后发现 \(a_i mod 4=s_{i-1}-a_{i-1}+2(a_d\mod 2)\),一次类推,就可以得出 \(a_i\) 的值。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=1e18;
const int N=1e5+5;;
int n,fa[N][20],hd[N],u[N],v[N],dep[N],e_num,lc[N];
struct edge{
	int v,nxt;
}e[N<<1];
void add_edge(int u,int v)
{
	e[++e_num]=(edge){v,hd[u]};
	hd[u]=e_num;
}
LL d[N],ans[N],ls[N];
LL read()
{
	LL s=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')
		ch=getchar();
	while(ch>='0'&&ch<='9')
		s=s*10+ch-48,ch=getchar();
	return s;
}
void dfs(int x,int y)
{
	dep[x]=dep[y]+1;
	fa[x][0]=y;
	for(int i=1;i<=18;i++)
		fa[x][i]=fa[fa[x][i-1]][i-1];
	for(int i=hd[x];i;i=e[i].nxt)
		if(e[i].v^y)
			dfs(e[i].v,x);
}
int lca(int x,int y)
{
	if(dep[x]<dep[y])
		swap(x,y);
	for(int i=18;~i;i--)
		if(dep[fa[x][i]]>=dep[y])
			x=fa[x][i];
	if(x==y)
		return x;
	for(int i=18;~i;--i)
		if(fa[x][i]^fa[y][i])
			x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
int main()
{
	n=read();
	for(int i=1;i<n;i++)
		add_edge(u[i]=read(),v[i]=read()),add_edge(v[i],u[i]);
	for(int i=2;i<=n;i++)
		d[i]=read();
	dfs(1,0);
	for(int i=2;i<=n;i++)
		lc[i]=lca(i,i-1);
	for(LL i=2;i<=INF;i<<=1)
	{
		for(int j=2;j<=n;j++)
			ans[j]=(d[j]-ans[j-1]+2*ls[lc[j]]+i)%i;
		memcpy(ls,ans,sizeof(ls));
	}
	for(int i=2;i<=n;i++)
		if(ans[fa[i][0]]>=ans[i]||ans[i]<0||ans[i]+ans[i-1]-2*ans[lc[i]]^d[i])
			return puts("-1"),0;
	for(int i=1;i<n;i++)
		printf("%lld\n",abs(ans[u[i]]-ans[v[i]]));
}

posted @ 2023-07-26 09:09  灰鲭鲨  阅读(28)  评论(0编辑  收藏  举报