bzoj2152(树形dp或点分治)

来源:互联网 发布:遗传算法原理与应用 编辑:程序博客网 时间:2024/06/06 01:55

算是点分治模板题。

用的一位神奔的模板,思路还是很清晰的。

不过这道题状态数(余数)只有0,1,2,所以其实树形dp就能搞,并且复杂度还低。算是点分治练手了。

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<cstdlib>using namespace std;const int N=20005;const int inf=0x3f3f3f3f;int n,rt,sum,ans,mi;int size[N];bool vis[N]; int head[N],tot;struct  aa{int pre,to,dis;}edge[N*2];void addedge(int x,int y,int z){edge[++tot].to=y;edge[tot].pre=head[x];head[x]=tot;edge[tot].dis=z;}void getsize(int u,int fa){size[u]=1;for (int i=head[u];i;i=edge[i].pre)if (fa!=edge[i].to&&!vis[edge[i].to]){getsize(edge[i].to,u);size[u]+=size[edge[i].to];}}void getrt(int u,int fa){int tmp=sum-size[u];for (int i=head[u];i;i=edge[i].pre)if (edge[i].to!=fa&&!vis[edge[i].to]){getrt(edge[i].to,u);tmp=max(tmp,size[edge[i].to]);}if (tmp<mi) mi=tmp,rt=u;}void dfs(int u,int fa,int dis,int cnt[]){cnt[dis]++;for (int i=head[u];i;i=edge[i].pre)if (fa!=edge[i].to&&!vis[edge[i].to])  dfs(edge[i].to,u,(dis+edge[i].dis)%3,cnt);}void work(int u){int cnt[3]={1,0,0};for (int i=head[u];i;i=edge[i].pre)if (!vis[edge[i].to]){int _cnt[3]={0,0,0};dfs(edge[i].to,u,edge[i].dis,_cnt);ans+=cnt[1]*_cnt[2]+cnt[2]*_cnt[1]+cnt[0]*_cnt[0];cnt[0]+=_cnt[0];cnt[1]+=_cnt[1];cnt[2]+=_cnt[2];}}void dfs(int u){getsize(u,0);mi=inf;sum=size[u];getrt(u,0);u=rt;vis[u]=true;work(u);for (int i=head[u];i;i=edge[i].pre)if (!vis[edge[i].to]) dfs(edge[i].to);}int main(){scanf("%d",&n);int x,y,z;for (int i=1;i<n;i++) {scanf("%d%d%d",&x,&y,&z);addedge(x,y,z%3);addedge(y,x,z%3);}dfs(1);ans=ans*2+n;int d=__gcd(ans,n*n);printf("%d/%d",ans/d,n*n/d);return 0; } 

总结

1:这里的模板是点分治的整体框架和找重心模板。

2:

0 0
原创粉丝点击