bzoj2152 聪聪可可【点分治】
2015-05-08 19:33
218 查看
题意:中文题。。。。。。
按点分治的的方法,每次都求出经过根的可行方案的个数,这里要求是3的倍数,所以我们可以把距离根的距离%3,那么取余后的距离根的距离为1和2的可以组成3,两个0当然也可以,这里用cnt[0],cnt[1],cnt[2]表示0,1,2的个数,对每个1可以有cnt[2]个2与他组成符合条件的路,所以数量就是cnt[1]*cnt[2],从2跑到1也可以所以还要*2,这个结果就是cnt[1]*cnt[2]*2。。然后考虑0的,,对每个0可以有cnt[0]-1个与他匹配,所以这个结果是cnt[0]*cnt[0]-cnt[0],然后每个0都可以直接与根相连,所以还要加cnt[0],结果也就是cnt[0]*cnt[0],最终结果就是cnt[1]*cnt[2]*2+cnt[0]*cnt[0]。。
然后就是还要减去在同一棵子树里的,。。。
按点分治的的方法,每次都求出经过根的可行方案的个数,这里要求是3的倍数,所以我们可以把距离根的距离%3,那么取余后的距离根的距离为1和2的可以组成3,两个0当然也可以,这里用cnt[0],cnt[1],cnt[2]表示0,1,2的个数,对每个1可以有cnt[2]个2与他组成符合条件的路,所以数量就是cnt[1]*cnt[2],从2跑到1也可以所以还要*2,这个结果就是cnt[1]*cnt[2]*2。。然后考虑0的,,对每个0可以有cnt[0]-1个与他匹配,所以这个结果是cnt[0]*cnt[0]-cnt[0],然后每个0都可以直接与根相连,所以还要加cnt[0],结果也就是cnt[0]*cnt[0],最终结果就是cnt[1]*cnt[2]*2+cnt[0]*cnt[0]。。
然后就是还要减去在同一棵子树里的,。。。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=20010; const int INF=1<<30; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } struct EDGE { int v,next; int val; }edge[MAXN<<1]; int head[MAXN],size; void init() { memset(head,-1,sizeof(head)); size=0; } void add_edge(int u,int v,int c) { edge[size].v=v; edge[size].val=c; edge[size].next=head[u]; head[u]=size++; } int num[MAXN],siz[MAXN],root,tot_size; bool vis[MAXN]; void get_root(int u,int fa) { num[u]=0; siz[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v]||v==fa) continue; get_root(v,u); siz[u]+=siz[v]; num[u]=max(num[u],siz[v]); } num[u]=max(num[u],tot_size-num[u]); if(num[root]>num[u]) root=u; } int cnt[3],dep[MAXN]; void get_dep(int u,int fa) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa||vis[v]) continue; dep[v]=dep[u]+edge[i].val; cnt[dep[v]%3]++; get_dep(v,u); } } int get_num(int u,int val) { dep[u]=val; memset(cnt,0,sizeof(cnt)); cnt[dep[u]%3]++; get_dep(u,-1); return cnt[0]*cnt[0]+cnt[1]*cnt[2]*2; } int ans; void dfs(int u) { vis[u]=1; ans+=get_num(u,0); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v]) continue; ans-=get_num(v,edge[i].val); } for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v]) continue; root=0; tot_size=siz[v]; get_root(v,-1); dfs(root); } } int main() { int n,i; while(scanf("%d",&n)==1) { init(); int u,v,c; for(i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&c); add_edge(u,v,c); add_edge(v,u,c); } memset(num,0,sizeof(num)); memset(vis,0,sizeof(vis)); root=0; num[root]=INF; tot_size=n; get_root(1,-1); ans=0; dfs(root); int temp=n*n; int d=gcd(ans,temp); printf("%d/%d\n",ans/d,temp/d); } return 0; }
相关文章推荐
- BZOJ 2152: 聪聪可可 分治
- BZOJ 2152 聪聪可可(点分治)
- 【BZOJ】2152: 聪聪可可(点分治)
- 【BZOJ 2152】聪聪可可 点分治
- BZOJ2152 聪聪可可 点分治入门
- [BZOJ2152]聪聪可可(点分治)
- BZOJ 2152 聪聪可可 [树分治 or 树形DP]
- BZOJ 题目2152: 聪聪可可(树的点分治)
- 洛谷 2634&&BZOJ 2152: 聪聪可可【点分治学习+超详细注释】
- 【bzoj2152】聪聪可可 点分治
- BZOJ2152 聪聪可可 点分治题解
- BZOJ 2152 聪聪可可 树的点分治/树形DP
- BZOJ 2152: 聪聪可可 点分治
- bzoj 2152: 聪聪可可(树的点分治)
- 【bzoj2152】聪聪可可 点分治
- bzoj2152 聪聪可可 点分治
- [bzoj2152]聪聪可可(点分治)
- BZOJ 2152: 聪聪可可 点分治
- [bzoj] 2152 聪聪可可 || 树分治
- bzoj2152 聪聪与可可 点分治