专栏文章

题解:P13099 [FJCPC 2025] VERTeX

P13099题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mioyqzet
此快照首次捕获于
2025/12/03 03:20
3 个月前
此快照最后确认于
2025/12/03 03:20
3 个月前
查看原文
[Analysis]\color{blue}{\texttt{[Analysis]}}
如果可以知道一个点的点权的话,那么 O(n)O(n) 的时间内我们可以把所有点的点权均求出来。
我们先考虑随机给点 11 赋上一个权值,那么可以把所有的 bu1b_{u}^{1} 求出来。当然这未必是一个合法的方案。
显然,可能会存在某个或某些点 vv,使得 bv10b_{v}^{1}\leq 0。考虑换根,将其中一个 vv 作为新的根,把它的点权取值为 11,然后求出 bu2b_{u}^{2}。当然 b2b^{2} 中可能仍然存在小于等于 00 的点,把它作为根继续迭代。
可以预见,如果无解,那么无论谁作为根都求不出合法解出来;如果有解,可以在有限次数的换根中得到合法的解。
由于 n2×105n \leq 2 \times 10^{5},可以考虑进行 100100 次换根,如果都无法求出合法解,就认为不存在合法解。
[Solution]\color{blue}{\texttt{[Solution]}}
  1. 11 作为原树的根节点。
  2. 将根节点的点权赋值为 11
  3. 迭代求出所有点的点权。
  4. 检查点权方案是否合法。如果合法,则跳转至步骤 66;否则找到一个点权小于等于 00 的点 vv
  5. vv 作为新树的根。如果迭代次数超过限制,跳转至步骤 77;否则回到步骤 22
  6. 输出合法方案,跳至步骤 88
  7. 输出无解,跳至步骤 88
  8. 程序结束。
Code\color{blue}{\text{Code}}
CPP
int val[N],n;
void dfs(int u,int Fa,int point){
	val[u]=point;
	for(int i=h[u];i;i=e[i].nxt){
		int v=e[i].to;
		if (v==Fa) continue;
		
		dfs(v,u,e[i].val-point);
	}
}
int check(int rt){
	dfs(rt,0,1);
	for(int i=1;i<=n;i++)
		if (val[i]<=0) return i;
	return 0;
}

int main(){
	n=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read(),val=read();
		add(u,v,val);add(v,u,val);
	}
	
	int rt=1;
	for(int i=1;i<=100;i++){
		int rec=check(rt);
		if (!rec){
			printf("YES\n");
			for(int i=1;i<=n;i++)
				printf("%d ",val[i]);
			return 0;
		}
		rt=rec;
	}
	
	printf("NO");
	
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...