BZOJ3697:采药人的路径(点分治)
Description
采药人的药田是一个树状结构,每条路径上都种植着同种药材。
采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多少种不同的路径。
Input
第1行包含一个整数N。
接下来N-1行,每行包含三个整数a_i、b_i和t_i,表示这条路上药材的类型。
Output
输出符合采药人要求的路径数目。
Sample Input
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1
Sample Output
Solution
用g[i][0…1],f[i][0…1]分别表示
前面几个子树以及当前子树路径长度和为i的路径数目
0和1用于区分路径上是否存在前缀和为i的节点(也就是可以设立中转站的节点)
那么当前子树的贡献就是f[0][0] * g[0][0] + Σf [i][0] * g [-i][1] + f[i][1] * g[-i][0] + f[i][1] * g[-i][1],
其中i的范围[-d,d],d为当前子树的深度。
Code
#include<iostream>
#include<cstring>
#include<cstdio>
#define N (200000+100)
using namespace std;
struct node
{
int to,next,len;
} edge[N*];
int n,k,sum,root,INF;
long long ans,g[N][],f[N][];
int t[N*];
int head[N],num_edge,max_depth;
int depth[N],d[N],size[N],maxn[N],dis[N];
bool vis[N]; void add(int u,int v,int l)
{
edge[++num_edge].to=v;
edge[num_edge].len=l;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void Get_root(int x,int fa)
{
size[x]=;
maxn[x]=;
for (int i=head[x]; i!=; i=edge[i].next)
if (!vis[edge[i].to] && edge[i].to!=fa)
{
Get_root(edge[i].to,x);
size[x]+=size[edge[i].to];
maxn[x]=max(maxn[x],size[edge[i].to]);
}
maxn[x]=max(maxn[x],sum-size[x]);
if (maxn[x]<maxn[root]) root=x;
} void Calc(int x,int fa)
{
max_depth=max(max_depth,depth[x]);
if (t[dis[x]]) f[dis[x]][]++;
else f[dis[x]][]++;
t[dis[x]]++;
for (int i=head[x]; i!=; i=edge[i].next)
if (edge[i].to!=fa && !vis[edge[i].to])
{
depth[edge[i].to]=depth[x]+;
dis[edge[i].to]=dis[x]+edge[i].len;
Calc(edge[i].to,x);
}
t[dis[x]]--;
} void Solve(int x)
{
vis[x]=true;
g[n][]=;//关于这里为什么初始化为1的问题,想了好久,最后还是学姐给我的解答
//http://blog.csdn.net/wu_tongtong/article/details/79428928
//可能路径是从当前树根到某一个节点的时候,路径已经平衡,不需要去另一个子树里面找另一个链拼接了
//所以这一部分的答案也要统计进去。
int up=;
for (int i=head[x]; i!=; i=edge[i].next)
if (!vis[edge[i].to])
{
depth[edge[i].to]=;
dis[edge[i].to]=edge[i].len+n;
max_depth=;
Calc(edge[i].to,);
up=max(up,max_depth); ans+=(g[n][]-)*f[n][];
for (int j=-max_depth; j<=max_depth; ++j)
ans+=g[n-j][]*f[n+j][]+g[n-j][]*f[n+j][]+g[n-j][]*f[n+j][];
for (int j=-max_depth; j<=max_depth; ++j)
{
g[n-j][]+=f[n-j][];
g[n-j][]+=f[n-j][];
f[n-j][]=f[n-j][]=;
}
}
for (int i=-up; i<=up; ++i)
g[n-i][]=g[n-i][]=;
for (int i=head[x]; i!=; i=edge[i].next)
if (!vis[edge[i].to])
{
sum=size[edge[i].to];
root=;
Get_root(edge[i].to,);
Solve(root);
}
} int main()
{
int u,v,l;
scanf("%d",&n);
sum=maxn[]=n;
for (int i=; i<=n-; ++i)
{
scanf("%d%d%d",&u,&v,&l);
add(u,v,l==?-:);
add(v,u,l==?-:);
}
Get_root(,);
Solve(root);
printf("%lld",ans);
}
BZOJ3697:采药人的路径(点分治)的更多相关文章
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- [bzoj3697]采药人的路径——点分治
Brief Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天 ...
- 【BZOJ3697】采药人的路径 点分治
[BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...
- [bzoj3697]采药人的路径_点分治
采药人的路径 bzoj-3697 题目大意:给你一个n个节点的树,每条边分为阴性和阳性,求满足条件的链的个数,使得这条链上阴性的边的条数等于阳性的边的条数,且这条链上存在一个节点,这个节点到一个端点的 ...
- bzoj千题计划248:bzoj3697: 采药人的路径
http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...
- BZOJ3697 采药人的路径 【点分治】
题目 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697: 采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动 ...
- 2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...
- BZOJ 3697/3127 采药人的路径 (点分治)
题目大意: 从前有一棵无向树,树上边权均为$0$或$1$,有一个采药人,他认为如果一条路径上边权为$0$和$1$的边数量相等,那么这条路径阴阳平衡.他想寻找一条合法的采药路径,保证阴阳平衡.然后他发现 ...
随机推荐
- 总结:Python学习 和 Python与C/C++交互
本篇仅仅是Python的学习和Python和C++数据对接过程中的一些总结. 由于工作的需要,用一周的时间学习 Python. Python是基于C实现的一门解释型语言,由于其易用性,俘获了不少开发者 ...
- webpack工具、Vue、react模块化
一.为什么要有webpack print('hello,world') fsdl fdsf title2 title3 引用 斜体字 加粗 有序列表1 有序列表2 无序列表1 无序列表2 行内code ...
- 如何在没有https环境下使用webrtc
新版本的webrtc使用需要Https,但是在内网开发调试时,要配置Https环境比较麻烦,下面的方法是教你如何在http下使用webrtc 1,点桌面上的Chrome图票,右键->属性,把目票 ...
- android inflate压力泵,将视图发生整合的过程
转自:https://blog.csdn.net/u012702547/article/details/52628453?utm_source=copy inflate方法从大范围来看,分两种,三个参 ...
- SpringBoot 之Quartz的使用
对于Quartz的使用,还是想说一句,SpringBoot真的很好用啊! 第一步:当然是引入依赖啦 <parent> <groupId>org.springframework. ...
- java web工程web.xml介绍
转载自:http://blog.csdn.net/believejava/article/details/43229361 Web.xml详解: 1.web.xml加载过程(步骤) 首先简单讲一下,w ...
- js 数组常用的一些方法
数组可以说是js经常会遇到的数据结构,以下我们对数组进行详细的学习! 一.数组的创建 var mycars = new Array(): || new Array(3); || new Array( ...
- 最全的HTTP 响应状态码列表!
摘要: HTTP状态码,我们要学会现查现用能记住最好. 简单举例几个常用的状态码,比如200,302,304,404, 503. 一般来说我也只需要了解这些常用的状态码就可以了.如果是做AJAX,RE ...
- 使用sql语句备份一张表
如何使用sql语句复制一张表? 方法一:第一步:先建一张新表,新表的结构与老表相等. create table newtable like oldtable; 第二步:将老表中的值复制到新标中. in ...
- 使用 maven 创建 java web 工程
本文主要讲述使用 maven 命令行的形式来创建 java web 工程 开发环境 jdk 1.7 maven 3.5.0 spring 3.2 tomcat 7 eclipse Mars Rele ...