#树形dp#BZOJ 2152 洛谷 2634 聪聪可可

题目

在一棵 n n n个点的树上找两个可以相同的点,问这两点间路径和是3的倍数的概率


分析

树形dp,方程比较简单,但是求答案比较难,所以详见代码,时间复杂度 O ( n ) O(n) O(n)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=20011;
struct node{int y,w,next;}e[N<<1];
int ls[N],dp[N][3],ans,n,k=1;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed gcd(int a,int b){return b?gcd(b,a%b):a;}
inline void dfs(int x,int fa){
	dp[x][0]=1;
	for (rr int i=ls[x];i;i=e[i].next)
	if (e[i].y!=fa){
		dfs(e[i].y,x);
		for (rr int j=0;j<3;++j)
		    ans+=dp[e[i].y][j]*dp[x][(6-e[i].w-j)%3]<<1;//意思就是该条路径上的答案乘不需要这条路径的答案,因为点对无序,所以要乘2
		for (rr int j=0;j<3;++j)
		    dp[x][(e[i].w+j)%3]+=dp[e[i].y][j];//就是传递答案
	}
}
signed main(){
	ans=n=iut();
	for (rr int i=1;i<n;++i){
		rr int x=iut(),y=iut(),w=iut()%3;
		e[++k]=(node){y,w,ls[x]},ls[x]=k,
		e[++k]=(node){x,w,ls[y]},ls[y]=k;
	}
	dfs(1,0);
	rr int all=n*n,Gcd=gcd(ans,all);
	return !printf("%d/%d",ans/Gcd,all/Gcd); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值