您的位置:首页 > 其它

bzoj2152 聪聪可可 点分治

2015-11-28 11:42 405 查看
点分治求路径长度为3的倍数的链的条数,结果用分数表示。

这道题明显是树形dp简单,然而还是写了点分治(练习所用没办法啊)。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 50005
using namespace std;

int n,m,tot,sum,rt,ans,t[3],fst
,pnt
,len
,nxt
,d
,sz
,f
;
bool vis
;
int read(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x;
}
void add(int aa,int bb,int cc){
pnt[++tot]=bb; nxt[tot]=fst[aa]; len[tot]=cc; fst[aa]=tot;
}
void dfs(int x,int fa){
sz[x]=f[x]=1; int p;
for (p=fst[x]; p; p=nxt[p]){
int v=pnt[p]; if (v==fa || vis[v]) continue;
dfs(v,x); sz[x]+=sz[v];
f[x]=max(f[x],sz[v]);
}
f[x]=max(f[x],sum-sz[x]); if (f[x]<f[rt]) rt=x;
}
void getdep(int x,int fa){
t[d[x]]++; int p;
for (p=fst[x]; p; p=nxt[p]){
int v=pnt[p]; if (v==fa || vis[v]) continue;
d[v]=(d[x]+len[p])%3; getdep(v,x);
}
}
int work(int x,int num){
d[x]=num; memset(t,0,sizeof(t));
getdep(x,0); return t[0]*t[0]+t[1]*t[2]*2;
}
void solve(int x){
ans+=work(x,0); vis[x]=1; int p;
for (p=fst[x]; p; p=nxt[p]){
int v=pnt[p]; if (vis[v]) continue;
ans-=work(v,len[p]);
sum=sz[v]; rt=0; dfs(v,x); solve(rt);
}
}
int gcd(int x,int y){ return (y)?gcd(y,x%y):x; }
void print_ans(int x,int y){
int tmp=gcd(x,y); printf("%d/%d\n",x/tmp,y/tmp);
}
int main(){
n=read(); int i;
for (i=1; i<n; i++){
int x=read(),y=read(),z=read()%3;
add(x,y,z); add(y,x,z);
}
f[rt=0]=sum=n; dfs(1,0);
solve(rt); print_ans(ans,n*n);
return 0;
}


2015.11.15

by lych
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: