BZOJ 2152 聪聪可可 树的点分治/树形DP
来源:互联网 发布:手机网络节点怎么改 编辑:程序博客网 时间:2024/05/23 10:12
题目大意:给定一棵树,每条边上有边权,求距离为3的倍数的有序点对
树的点分治,对于每个重心统计出每棵子树距离重心长度为0/1/2的点的数量,计算出ans即可
最后ans*2+1 和n^2进行一下约分即可
其实我上当了……这题根本就没必要写树的点分治,直接树形DP就出来了
开一个三元组记录某棵子树中距离子树的根节点距离为某值的点的个数
然后直接统计+转移就行了
树的点分治:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 20200using namespace std;struct abcd{int to,f,next;bool ban;}table[M<<1];int head[M],tot=1;int n,ans;int siz[M];void Add(int x,int y,int z){table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;}void Get_Centre_Of_Gravity(int x,int from,int size,int &cg){int i;siz[x]=1;bool flag=1;for(i=head[x];i;i=table[i].next){if(table[i].ban||table[i].to==from)continue;Get_Centre_Of_Gravity(table[i].to,x,size,cg);if(siz[table[i].to]>size>>1)flag=0;siz[x]+=siz[table[i].to];}if(size-siz[x]>size>>1)flag=0;if(flag)cg=x;}void DFS(int x,int from,int dis,int cnt[]){int i;siz[x]=1;cnt[dis]++;for(i=head[x];i;i=table[i].next){if(table[i].ban||table[i].to==from)continue;DFS(table[i].to,x,(dis+table[i].f)%3,cnt);siz[x]+=siz[table[i].to];}}void Calculate(int x){int i;int cnt[3]={1,0,0};for(i=head[x];i;i=table[i].next){if(table[i].ban)continue;int _cnt[3]={0};DFS(table[i].to,x,table[i].f,_cnt);ans+=cnt[0]*_cnt[0];ans+=cnt[1]*_cnt[2];ans+=cnt[2]*_cnt[1];cnt[0]+=_cnt[0];cnt[1]+=_cnt[1];cnt[2]+=_cnt[2];}}void Tree_Divide_And_Conquer(int root,int size){int i,cg;if(size==1)return;Get_Centre_Of_Gravity(root,0,size,cg);Calculate(cg);for(i=head[cg];i;i=table[i].next){if(table[i].ban)continue;table[i].ban=table[i^1].ban=1;Tree_Divide_And_Conquer(table[i].to,siz[table[i].to]);}}int GCD(int x,int y){return y?GCD(y,x%y):x;}int main(){int i,x,y,z;cin>>n;for(i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);Add(x,y,z%3);Add(y,x,z%3);}Tree_Divide_And_Conquer(1+n>>1,n);ans=ans*2+n;int gcd=GCD(ans,n*n);cout<<ans/gcd<<'/'<<n*n/gcd<<endl;}
树形DP:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define M 20200using namespace std;struct triple{int x,y,z;triple(int _=0,int __=0,int ___=0):x(_),y(__),z(___){}void Rotate(){swap(x,y);swap(x,z);}void operator += (const triple &_){x+=_.x;y+=_.y;z+=_.z;}};struct abcd{int to,f,next;}table[M<<1];int head[M],tot;int n,ans;triple f[M];void Add(int x,int y,int z){table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;}void Tree_DP(int x,int from){int i;f[x]=triple(1,0,0);for(i=head[x];i;i=table[i].next){if(table[i].to==from)continue;Tree_DP(table[i].to,x);for(;table[i].f;table[i].f--)f[table[i].to].Rotate();ans+=f[x].x*f[table[i].to].x;ans+=f[x].y*f[table[i].to].z;ans+=f[x].z*f[table[i].to].y;f[x]+=f[table[i].to];}}int main(){int i,x,y,z;cin>>n;for(i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);Add(x,y,z%3);Add(y,x,z%3);}Tree_DP(1,0);ans=ans*2+n; int gcd=__gcd(ans,n*n); cout<<ans/gcd<<'/'<<n*n/gcd<<endl; }
0 0
- BZOJ 2152: 聪聪可可(点分治/树形DP)
- BZOJ 2152 聪聪可可 树的点分治/树形DP
- BZOJ 2152 聪聪可可 [树分治 or 树形DP]
- BZOJ 2152: 聪聪可可 点分治/树dp
- BZOJ 2152 聪聪可可 树的点分治
- bzoj 2152: 聪聪可可(树的点分治)
- 【bzoj 2152】聪聪可可(树的点分治)
- 【BZOJ】2152: 聪聪可可 点分治
- bzoj 2152: 聪聪可可 点分治
- 【BZOJ 2152】聪聪可可 点分治
- Bzoj 2152: 聪聪可可(点分治)
- BZOJ 2152: 聪聪可可 点分治
- 【BZOJ】2152 聪聪可可 点分治
- BZOJ 2152: 聪聪可可 点分治
- BZOJ2152 聪聪可可(树形DP/点分治)
- BZOJ 2152: 聪聪可可【树形dp
- BZOJ 题目2152: 聪聪可可(树的点分治)
- 【树分治】 BZOJ 2152 聪聪可可
- iostream 继承结构
- 运行myeclipse时提示workspace下的.metadata下的.log 有错误的解决方案
- TCP拥塞原理-重要
- wamp apache 2.1 配置
- R:返回值
- BZOJ 2152 聪聪可可 树的点分治/树形DP
- 室内地图定位技术应用探讨,室内地图应用开发交流
- HASH JOIN , MERGE JOIN ,NESTED LOOP
- [Java 8] (7) 利用Stream类型的"懒"操作
- NSOpenPanel 使用(MAC 打开文件夹对话框的使用)
- 重温一下bat命令
- 黄金数据查询演示示例
- 第9周项目3-输出星号图(d)
- mkfs.jffs2 参数