BZOJ_3697_采药人的路径_点分治

Description

采药人的药田是一个树状结构,每条路径上都种植着同种药材。
采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多少种不同的路径。

Input

第1行包含一个整数N。
接下来N-1行,每行包含三个整数a_i、b_i和t_i,表示这条路上药材的类型。

Output

输出符合采药人要求的路径数目。

Sample Input

7
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1

Sample Output

1

HINT

对于100%的数据,N ≤ 100,000。


路径计数问题,很容易想到点分治。把0当成-1,那么路径长度为0的路径就是阴阳平衡的。

设f[i][0/1]表示到根的路径长度为i,且路径上没有/有阴阳平衡的路径的路径条数。

设g[i][0/1]表示到根的路径长度为-i,且路径上没有/有阴阳平衡的路径的路径条数。

对答案的贡献为f[i][0]*g[i][1]+f[i][1]*g[i][0]+f[i][1]*g[i][1]

然后发现向下找路径的时候长度一定是一个范围(因为边权为1或-1),我们记录这个范围就能求出这条路径上还有没有平衡的了。

其他细节比较多

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 200050
typedef long long ll;
int head[N],to[N<<1],nxt[N<<1],val[N<<1],cnt;
int n,fag[N],siz[N],tot,root,maxdeep;
bool used[N];
ll ans,f[N][2],g[N][2];
inline void add(int u,int v,int w) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
}
void getroot(int x,int y) {
fag[x]=0; siz[x]=1;
int i;
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=y&&!used[to[i]]) {
getroot(to[i],x);
siz[x]+=siz[to[i]];
fag[x]=max(fag[x],siz[to[i]]);
}
}
fag[x]=max(fag[x],tot-siz[x]);
if(fag[root]>fag[x]) root=x;
}
void calc(int x,int y,int now,int cnt) {
int i;
if(now==0) {
if(cnt>=2) ans++;
cnt++;
}
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=y&&!used[to[i]]) {
calc(to[i],x,now+val[i],cnt);
}
}
}
void getdep(int x,int y,int now,int l,int r) {
siz[x]=1;
int i;
if(now>=l&&now<=r) {
if(now>=0) f[now][1]++;
else g[-now][1]++;
}else {
if(now>=0) f[now][0]++;
else g[-now][0]++;
}
l=min(l,now); r=max(r,now); maxdeep=max(maxdeep,max(-l,r));
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=y&&!used[to[i]]) {
getdep(to[i],x,now+val[i],l,r);
siz[x]+=siz[to[i]];
}
}
}
void work(int x) {
int i,j;
used[x]=1; maxdeep=0; calc(x,0,0,0);
getdep(x,0,0,1,-1); ans+=f[0][1]*(f[0][1]-1)/2; f[0][0]=f[0][1]=0;
for(i=1;i<=maxdeep;i++) ans+=f[i][1]*g[i][1]+f[i][0]*g[i][1]+f[i][1]*g[i][0],f[i][0]=f[i][1]=g[i][0]=g[i][1]=0;
for(i=head[x];i;i=nxt[i]) {
if(!used[to[i]]) {
maxdeep=0; getdep(to[i],0,val[i],0,0); ans-=f[0][1]*(f[0][1]-1)/2; f[0][0]=f[0][1]=0;
for(j=1;j<=maxdeep;j++) ans-=f[j][1]*g[j][1]+f[j][0]*g[j][1]+f[j][1]*g[j][0],f[j][0]=f[j][1]=g[j][0]=g[j][1]=0;
tot=siz[to[i]];
root=0;
getroot(to[i],0);
work(root);
}
}
}
int main() {
scanf("%d",&n);
int i,x,y,z;
for(i=1;i<n;i++) {
scanf("%d%d%d",&x,&y,&z);
if(!z) z--;
add(x,y,z); add(y,x,z);
}
tot=n;
fag[0]=1<<30;
getroot(1,0);
work(root);
printf("%lld\n",ans);
}

BZOJ_3697_采药人的路径_点分治的更多相关文章

  1. [bzoj3697]采药人的路径_点分治

    采药人的路径 bzoj-3697 题目大意:给你一个n个节点的树,每条边分为阴性和阳性,求满足条件的链的个数,使得这条链上阴性的边的条数等于阳性的边的条数,且这条链上存在一个节点,这个节点到一个端点的 ...

  2. 【BZOJ-3697&3127】采药人的路径&YinandYang 点分治 + 乱搞

    3697: 采药人的路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 681  Solved: 246[Submit][Status][Discus ...

  3. BZOJ3697 采药人的路径 【点分治】

    题目 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药活动.他选择的路径 ...

  4. 【BZOJ3697】采药人的路径(点分治)

    题意:采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径是很 ...

  5. BZOJ3697: 采药人的路径(点分治)

    Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动 ...

  6. 2019.01.09 bzoj3697: 采药人的路径(点分治)

    传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...

  7. bzoj 3697: 采药人的路径【点分治】

    点分治,设当前处理的块的重心为rt,预处理出每个子树中f[v][0/1]表示组合出.没组合出一对值v的链数(从当前儿子出发的链),能组合出一对v值就是可以有一个休息点 然后对于rt,经过rt且合法的路 ...

  8. 【BZOJ3697】采药人的路径 点分治

    [BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...

  9. BZOJ_1316_树上的询问_点分治

    BZOJ_1316_树上的询问_点分治 Description 一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No. Input 第一行两个整 ...

随机推荐

  1. Django(一)入门基础——hello world

    环境配置 windows7 python3.6 Django 2.0 PyCharm 2018.1 专业版(PS:不建议社区版,因为被"阉割"了很多功能,比如cmd的Termina ...

  2. 实施一个SAP项目大概分为下面几个过程

    实施一个SAP项目大概分为下面几个过程 1.需求调研.了解客户需要实施的范围,比如是财务模块,后勤模块,人力资源,商务智能等等.需求调研通常有几种方法了解,和客户开会讨论:分配到具体业务人员了解:通过 ...

  3. Ibatis和Hibernate的比较

    Ibatis和Hibernate的比较 分类: IBATIS HIBERNATE2010-11-19 17:58 341人阅读 评论(0) 收藏 举报 hibernateibatis数据库sqlcac ...

  4. RESTful规范建议

    RESTful概述 RESTful是目前最流行的一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. REST是Representational State T ...

  5. Hbase出现ERROR: Can't get master address from ZooKeeper; znode data == null正确找到解决思路

    第一次配置时出现这样的错误,也很懵的,到处上网找博客看资料,都试了个遍,但是问题还是存在,以下这些博客写的或许是解决一类问题的方式. https://blog.csdn.net/whbo111/art ...

  6. Ubuntu16.04下安装Hadoop

    一.记录理由 刚开始只是想要学习怎么使用Hive的.想着安装应该很简单,没想到花了整整一天的时间来安装,为了避免下次犯同样的错误,特此记录. 二.安装Hadoop 网上教你怎么安装Hadoop的文章有 ...

  7. SSM博客

    最近在写基于SSM 的博客,用的是spring+springmvc+mybatis搭建的,用的maven+github管理项目,目前完成了登录注册以及用户管理员的增删改查,后续的功能还需要完善,如何建 ...

  8. .net(C#)在Access数据库中执行sql脚本

    自己写的一个工具类,主要是业务场景的需要. 主要有两个功能: ①执行包含sql语句的字符串 ②执行包含sql语句的文件 调用方式 /// <summary> /// 执行sql语句 /// ...

  9. 杨老师课堂之JavaScript定时器_农夫山泉限时秒杀案例

    预览效果图: 使用到的知识点: 定时器 setInterval(函数,毫秒):在指定的毫秒数后调用函数或执行一段代码 取消定时器 clearInterval:取消由setInterval设置的定时器 ...

  10. mybatis自定义代码生成器(Generator)——自动生成model&dao代码

    花了两天的时间研究了下mybatis的generator大体了解了其生成原理以及实现过程.感觉generator做的非常不错,给开发者也留足了空间.看完之后在generator的基础上实现了自定义的生 ...