题意

一棵树,给定边权,求满足两点之间的路径上权值和为3的倍数的点对数量.

分析

点分治板题,对每个重心求子树下面的到根的距离模3分别为0,1,2的点的个数就行了.

O(3nlogn)O(3nlogn)O(3nlogn)

CODE

#include<bits/stdc++.h>
using namespace std;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &res) {
char ch; int flg = 1; for(;!isdigit(ch=getc());)if(ch=='-')flg=-flg;
for(res=ch-'0';isdigit(ch=getc());res=res*10+ch-'0'); res*=flg;
}
const int MAXN = 20005;
int n, fir[MAXN], cnt; bool ban[MAXN];
struct edge{ int to, nxt, w; }e[MAXN<<1];
inline void link(int u, int v, int wt) {
e[++cnt] = (edge){ v, fir[u], wt }, fir[u] = cnt;
e[++cnt] = (edge){ u, fir[v], wt }, fir[v] = cnt;
} int Get_Size(int x, int ff) { //求SIZE
int re = 1;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff) re += Get_Size(v, x);
return re;
}
int Get_Root(int x, int ff, int Size, int &G) { //找重心
int re = 1; bool flg = true;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff) {
int temp = Get_Root(v, x, Size, G);
if(temp<<1 > Size) flg = false;
re += temp;
}
if(Size-re<<1 > Size) flg = false;
if(flg) G = x;
return re;
}
int now[3], tmp[3], Ans;
void Count(int x, int ff, int dis) {
++tmp[dis];
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to] && v != ff) Count(v, x, (dis+e[i].w)%3);
}
inline void Solve(int x) { //算答案
now[0] = now[1] = now[2] = 0;
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to]) {
tmp[0] = tmp[1] = tmp[2] = 0;
Count(v, x, e[i].w);
Ans += tmp[0] * now[0] << 1;
Ans += tmp[1] * now[2] << 1;
Ans += tmp[2] * now[1] << 1;
now[0] += tmp[0];
now[1] += tmp[1];
now[2] += tmp[2];
}
Ans += (now[0]<<1) + 1;
}
void TDC(int x) { //点分治
int Size = Get_Size(x, 0);
Get_Root(x, 0, Size, x);
Solve(x); ban[x] = 1; //打标记
for(int v, i = fir[x]; i; i = e[i].nxt)
if(!ban[v=e[i].to]) TDC(v);
}
int main() {
read(n);
for(int i = 1, x, y, z; i < n; ++i)
read(x), read(y), read(z), link(x, y, z%3);
TDC(1);
int d = Ans ? __gcd(Ans, n*n) : 1;
printf("%d/%d\n", Ans/d, n*n/d);
}

UpdUpdUpd…sb了…直接树形DP不就完事了… O(3n)O(3n)O(3n)

CODE

(粘来的代码)

// luogu-judger-enable-o2
#include<cstdio>
#include<cctype>
#define maxn 20005
char cb[1<<15],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
char c;while(!isdigit(c=getc()));
for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
int n,ans,f[maxn][3],g[3];
int fir[maxn],nxt[maxn<<1],to[maxn<<1],w[maxn<<1],tot;
inline void line(int x,int y,int z){nxt[++tot]=fir[x];fir[x]=tot;to[tot]=y;w[tot]=z;}
void dfs(int u,int pre){
f[u][0]=1;
for(int i=fir[u],v;i;i=nxt[i]) if((v=to[i])!=pre){
dfs(v,u);
for(int j=0;j<3;j++) g[(j+w[i])%3]=f[v][j];
for(int j=0;j<3;j++) ans+=f[u][j]*g[j?3-j:0],f[u][j]+=g[j];
}
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main()
{
#ifndef ONLINE_JUDGE
freopen("H.in","r",stdin);
#endif
read(n);
for(int i=1,x,y,z;i<n;i++) read(x),read(y),read(z),line(x,y,z),line(y,x,z);
dfs(1,0);
ans=ans*2+n;
int d=gcd(ans,n*n);
printf("%d/%d",ans/d,n*n/d);
}

BZOJ 2152 / Luogu P2634 [国家集训队]聪聪可可 (点分治/树形DP)的更多相关文章

  1. luogu P2634 [国家集训队]聪聪可可 点分治

    Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...

  2. BZOJ 2127 / Luogu P1646 [国家集训队]happiness (最小割)

    题面 BZOJ传送门 Luogu传送门 分析 这道题又出现了二元关系,于是我们只需要解方程确定怎么连边就行了 假设跟SSS分在一块是选文科,跟TTT分在一块是选理科,先加上所有的收益,再来考虑如何让需 ...

  3. [BZOJ2152]聪聪可可 点分治/树形dp

    2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MB Submit: 3602  Solved: 1858 [Submit][Status][Discu ...

  4. [LUOGU] P2634 [国家集训队]聪聪可可

    点分治裸题,甚至不需要栈回撤. 尝试用容斥写了一波,就是把所有子树混一块计算,最后减去子树内路径条数. #include<iostream> #include<cstring> ...

  5. bzoj2152 / P2634 [国家集训队]聪聪可可(点分治)

    P2634 [国家集训队]聪聪可可 淀粉质点分治板子 边权直接 mod 3 直接点分治统计出所有的符合条件的点对再和总方案数约分 至于约分.....gcd搞搞就好辣 #include<iostr ...

  6. 洛谷 P2634 [国家集训队]聪聪可可 解题报告

    P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一 ...

  7. 洛谷 P2634 [国家集训队]聪聪可可-树分治(点分治,容斥版) +读入挂+手动O2优化吸点氧才过。。。-树上路径为3的倍数的路径数量

    P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...

  8. P2634 [国家集训队]聪聪可可(题解)(点分治)

    P2634 [国家集训队]聪聪可可(题解)(点分治) 洛谷题目 #include<iostream> #include<cstdlib> #include<cstdio& ...

  9. 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)

    洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...

随机推荐

  1. 分库分表之后,id 主键如何处理

    基于数据库的实现方案 数据库自增 id 这个就是说你的系统里每次得到一个 id,都是往一个库的一个表里插入一条没什么业务含义的数据,然后获取一个数据库自增的一个 id.拿到这个 id 之后再往对应的分 ...

  2. MQTT安全篇

    物联网的核心是连接万物,通过交换并分析数据使得生活更舒适与便捷.不过,敏感数据泄露或者设备被非法控制可不是闹着玩的.比如前段时间国内某著名家电企业的智能洗衣机,使用了某著名电商基于XMPP协议的物联网 ...

  3. SQL 拼接字符串 使用IN查询方法

    问题描述 当在 SQL SERVER 中查询的时候,同事遇到一个字段存储的字符串为用逗号分隔的主键 ID 值,格式为:1,2,3,4,这时候需要查询符合条件的所有数据,所以选择使用 IN 查询,但是直 ...

  4. Android UI组件:布局管理器

    为了更好的管理Android应用的用户界面中的组件,Android提供了布局管理器.通过使用布局管理器,Android应用的图形用户界面具有良好的平台无关性.通常,推荐使用布局管理器来管理组件的分布. ...

  5. Python特色数据类型--元组

    元组是不可改变的,创建后就不能做任何修改操作了 1.元组用()表示

  6. 大数据测试类型&大数据测试步骤

    一.什么是大数据? 大数据是一个大的数据集合,通过传统的计算技术无法进行处理.这些数据集的测试需要使用各种工具.技术和框架进行处理.大数据涉及数据创建.存储.检索.分析,而且它在数量.多样性.速度方法 ...

  7. Unity Button按钮延迟

    1.把下面脚本放到Editor文件夹下,这样脚本继承Button之后,新声明的public变量才能在Inspector面板显示出来. using System.Collections; using S ...

  8. .NET监视程序运行时间

    使用Stopwatch类(命名空间:System.Diagnostics;) 示例: using System; using System.Collections.Generic; using Sys ...

  9. Facebook 一个热搜帖,美国一个老人癌症不治最后的心愿是跟儿子喝啤酒。

    今天早上起床看到这个Facebook上的热搜帖.太感动了.这个老人癌症不治后最后心愿是跟他的儿子们一起喝一次啤酒.这个帖子被他孙子贴上网以后牵动了千万人的心.

  10. centos7安装nginx服务

    Nginx发音引擎x是一个免费的开源高性能HTTP和反向代理服务器,负责处理互联网上一些最大的网站的负载. 本教程将教你如何在你的CentOS Linux 7.5机器上安装和管理Nginx. 安装Ng ...