您的位置:首页 > 其它

bzoj2152 树形DP

2016-09-15 21:47 176 查看
听说这题还有点分治做法。。。

传送门:BZOJ2152

用dp[i][j]表示从i的子树中的点到i有多少条路径%3为j

强行树形DP

/**************************************************************
Problem: 2152
User: SmallFat
Language: C++
Time : 232ms
 Result: Accepted
****************************************************************/

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxn 101111
using namespace std;
struct edges{
int r,nxt,w;
}e[maxn<<1];
int head[maxn],esz;
long long ans=0,dp[maxn][3];
long long gcd(long long a,long long b){
return b?gcd(b,a%b):a;
}
void dfs(int n,int fa){

dp
[0]++;
for(int i=head
;i;i=e[i].nxt){
int m=e[i].r;
if(m==fa)continue;
dfs(m,n);
ans+=dp
[0]*dp[m][(3-e[i].w)%3];
ans+=dp
[1]*dp[m][(3+2-e[i].w)%3];
ans+=dp
[2]*dp[m][(3+1-e[i].w)%3];
for(int j=0;j<3;++j)
dp
[(j+e[i].w)%3]+=dp[m][j];

}

}
void addedge(int x,int y,int w){
e[++esz].r=y;e[esz].nxt=head[x];head[x]=esz;e[esz].w=w;
e[++esz].r=x;e[esz].nxt=head[y];head[y]=esz;e[esz].w=w;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<n;++i){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
addedge(a,b,w%3);
}
dfs(1,0);
ans=ans*2+n;
long long x=n*n;
long long g=gcd(x,ans);
printf("%lld/%lld",ans/g,x/g);
}

话说这不一水题吗。。。我竟然调啦好久
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: