模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)
静态点分治
一开始还以为要把分治树建出来……
• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法。
• A:朴素做法,直接找重心,处理过重心的所有路径。然而,路径端点在同一子树(即路径实际上并不过重心)的情况会发生重复计数,需要使用类似容斥的方法,不断删去重复计数的部分。
• B:采用类似树形背包的思路,遍历子树时,只考虑当前子树和先前处理完的多颗子树之间的路径,以保证路径端点在不同的子树中,防止重复计数,不需要麻烦的容斥。在一些更为复杂的情况下,方法A不能解决问题,可以在方法B的基础上结合数据结构来解决。因此,方法B适用范围更广,细节更少不易错(个人观点),推荐大家使用。
感觉桶比较难以理解……容斥就是先更新整颗树的答案,然后处理lca是子树的答案。
#include<iostream>
#include<cstring>
#include<cstdio>
#define MAXN 20010
#define LL long long
#define INF 1000000000
using namespace std;
struct edge
{
int u,v,w,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define w(x) ed[x].w
#define n(x) ed[x].nxt
}ed[MAXN*2];
int first[MAXN],num_e;
#define f(x) first[x]
int n;
int sum,mn,root;
int size[MAXN],mxsize[MAXN];
bool v[MAXN];
LL ans,cnt[3];
void getroot(int x,int fa)//找根节点
{
size[x]=1,mxsize[x]=0;
for(int i=f(x);i;i=n(i))
if(v(i)!=fa&&!v[v(i)])
{
getroot(v(i),x);
size[x]+=size[v(i)];
mxsize[x]=max(mxsize[x],size[v(i)]);
}
mxsize[x]=max(mxsize[x],sum-size[x]);
if(mxsize[x]<mn)mn=mxsize[x],root=x;
}
void ask(int x,int fa,int l)
{
cnt[l%3]++;
for(int i=f(x);i;i=n(i))
if(v(i)!=fa&&!v[v(i)])
ask(v(i),x,(l+w(i))%3);
}
int solve(int x,int add)
{
cnt[0]=cnt[1]=cnt[2]=0;
ask(x,0,add);
return 2ll*cnt[1]*cnt[2]+cnt[0]*cnt[0];
}
void divide(int x)
{
ans+=solve(x,0),v[x]=1;//更新答案
for(int i=f(x);i;i=n(i))
if(!v[v(i)])
{
ans-=solve(v(i),w(i));//容斥去重
sum=size[v(i)],mn=INF;
getroot(v(i),0);
divide(root);
}
}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
inline void add(int u,int v,int w);
inline int read()
{
int s=0;char a=getchar();
while(a<'0'||a>'9')a=getchar();
while(a>='0'&&a<='9'){s=s*10+a-'0',a=getchar();}
return s;
}
signed main()
{
cin>>n;
int u,v,w;
for(int i=1;i<n;i++)
{
u=read(),v=read(),w=read();
add(u,v,w%3);add(v,u,w%3);
}
sum=n;mn=INF;
getroot(1,0);
divide(root);
LL fm=n*n;
int GCD=gcd(ans,fm);
printf("%lld/%lld\n",ans/GCD,fm/GCD);
}
inline void add(int u,int v,int w)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
w(num_e)=w;
n(num_e)=f(u);
f(u)=num_e;
}
模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)的更多相关文章
- 洛谷 P2634 [国家集训队]聪聪可可-树分治(点分治,容斥版) +读入挂+手动O2优化吸点氧才过。。。-树上路径为3的倍数的路径数量
P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...
- 洛谷P2634 [国家集训队]聪聪可可(点分治)
传送门 题意: 给出一颗树,每条边都有一定的边权. 先问点之间路径和为\(3\)的倍数的点对有多少. 思路: 点分治模板题. 可以将问题转化为经过一个点\(t\)的路径和不经过点\(t\)的路径两种情 ...
- 洛谷P2634 [国家集训队]聪聪可可 (点分治)
题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...
- 洛谷-P2634 [国家集训队]聪聪可可 点分治
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- 洛谷P2634 [国家集训队]聪聪可可 点分治模板
题意 在一棵树上任意选两个点,求它们距离模3为0的概率. 分析 树分治模板 Code #include<bits/stdc++.h> #define fi first #define se ...
- [洛谷P2634][国家集训队]聪聪可可
题目大意:给你一棵树,随机选两个点,求它们之间路径长度是$3$的倍数的概率 题解:点分治,求出当前状态的重心,然后求出经过重心的答案,接着分治每棵子树.注意考虑重复计算的情况 卡点:无 C++ Cod ...
- 洛谷 P2634 [国家集训队]聪聪可可 解题报告
P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一 ...
- 洛谷 P2634 [国家集训队]聪聪可可
点分板子2333 注释都是错过的地方 #include<cstdio> #include<algorithm> using namespace std; typedef lon ...
- 洛谷P1501 [国家集训队]Tree II(LCT,Splay)
洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...
随机推荐
- Python缩进和选择
Python缩进和选择 缩进 Python最具特色的是用缩进来标明成块的代码.我下面以if选择结构来举例.if后面跟随条件,如果条件成立,则执行归属于if的一个代码块. 先看C语言的表达方式(注意,这 ...
- java opencv 4.0.1安装配置
如果没有把dll扔到jdk会报错 Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: no ...
- javax.el.PropertyNotFoundException: Property 'studentAge' not found on type com.hs.model.StudentModel
mi明明已经把这个字段重构了,为啥还这样提示呢?整个工程全部 查找也找不到这个字段了啊
- GIT → 11:Git 工作流与实战演练
GIT → 11:Git 工作流与实战演练
- java-String-StringBuffer
一 String 1.1 == 和 equal() System.out.println("-------两个内容相同,创建方式不同的字符串,面试题--------"); Stri ...
- PHPStrom直接在编辑器打开php文件
以下是自己配置PHP+Apache的开发环境,集成环境的话要换第二种方法(看个人配置):PHPStrom 如果希望直接在编辑器打开php文件,要做以下这几步配置. 第一种:非集成环境 1 2 3 第二 ...
- Android学习笔记之mainfest文件中android属性
android:allowTaskReparenting 是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务. -------------------------------- ...
- python编写购物车小程序
#练习#程序购物车#启动程序后,让用户输入工资, 然后打印商品列表,允许用户根据商品编号购买商品用户选择商品后 #检测余额是否够,够就直接扣款,不够就提醒可随时退出,退出时,打印已购买商品和余额 ...
- [C#] 使用WebSocket进行通讯
客户端 客户端很简单 string url = "ws://localhost:24900/" + "test.ashx"; try { System.Net. ...
- 几种常见的flex布局
1,水平等距排列.俩端对齐.垂直方向居顶对齐 html: <div class="container flex"> <div class="div1&q ...