【BZOJ3697】采药人的路径(点分治)
题意:采药人的药田是一个树状结构,每条路径上都种植着同种药材。
采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多少种不同的路径。
n<=100000
思路:RYZ作业
From hzwer:
来自出题人hta的题解。。
本题可以考虑树的点分治。问题就变成求过根满足条件的路径数。
路径上的休息站一定是在起点到根的路径上,或者根到终点的路径上。
如何判断一条从根出发的路径是否包含休息站?只要在dfs中记录下这条路径的和x,同时用个标志数组判断这条路径是否存在前缀和为x的节点。
这样我们枚举根节点的每个子树。用f[i][0…1],g[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为当前子树的深度。
var head,vet,next,len,d,dis,son,flag,dep:array[..]of longint;
c:array[..]of longint;
b:array[-..]of longint;
f,g:array[-..,..]of int64;
n,m,i,x,y,z,tot,sum,root,mxdep:longint;
ans:int64; procedure add(a,b,c:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; procedure getroot(u,fa:longint);
var e,v:longint;
begin
son[u]:=; c[u]:=;
e:=head[u];
while e<> do
begin
v:=vet[e];
if (v<>fa)and(flag[v]=) then
begin
getroot(v,u);
son[u]:=son[u]+son[v];
c[u]:=max(c[u],son[v]);
end;
e:=next[e];
end;
c[u]:=max(c[u],sum-c[u]);
if c[u]<c[root] then root:=u;
end; procedure dfs(u,fa:longint);
var e,v:longint;
begin
mxdep:=max(mxdep,dep[u]);
if b[dis[u]]> then inc(f[dis[u],])
else inc(f[dis[u],]);
inc(b[dis[u]]);
e:=head[u];
while e<> do
begin
v:=vet[e];
if (v<>fa)and(flag[v]=) then
begin
dep[v]:=dep[u]+;
dis[v]:=dis[u]+len[e];
dfs(v,u);
end;
e:=next[e];
end;
dec(b[dis[u]]);
end; procedure solve(u:longint);
var e,v,i,mx:longint;
begin
mx:=;
flag[u]:=; g[,]:=;
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
dis[v]:=len[e];
dep[v]:=; mxdep:=;
dfs(v,u);
mx:=max(mx,mxdep);
ans:=ans+(g[,]-)*f[,];
for i:=-mxdep to mxdep do
ans:=ans+g[-i,]*f[i,]+g[-i,]*f[i,]+g[-i,]*f[i,];
for i:=-mxdep to mxdep do
begin
g[i,]:=g[i,]+f[i,];
g[i,]:=g[i,]+f[i,];
f[i,]:=; f[i,]:=;
end;
end;
e:=next[e];
end;
for i:=-mx to mx do
begin
g[i,]:=; g[i,]:=;
end;
e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
sum:=son[v]; root:=;
getroot(v,);
solve(root);
end;
e:=next[e];
end;
end; begin
assign(input,'bzoj3697.in'); reset(input);
assign(output,'bzoj3697.out'); rewrite(output);
readln(n);
for i:= to n- do
begin
readln(x,y,z);
if z= then z:=-;
add(x,y,z);
add(y,x,z);
end;
root:=; sum:=n; c[]:=n;
getroot(,);
solve(root);
writeln(ans);
close(input);
close(output);
end.
【BZOJ3697】采药人的路径(点分治)的更多相关文章
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- BZOJ3697:采药人的路径(点分治)
Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药 ...
- [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$的边数量相等,那么这条路径阴阳平衡.他想寻找一条合法的采药路径,保证阴阳平衡.然后他发现 ...
随机推荐
- 224 Basic Calculator 基本计算器
实现一个基本的计算器来计算一个简单的字符串表达式. 字符串表达式可以包含左括号 ( ,右括号),加号+ ,减号 -,非负整数和空格 . 假定所给的表达式语句总是正确有效的. 例如: "1 + ...
- 【RSA】在 ASP.NET Core中结合web前端JsEncrypt.JS使用公钥加密,.NET Core使用私钥解密;
有一个需求,前端web使用的是JsEncrypt把后端给的公钥对密码进行加密,然后后端对其进行解密: 使用的类库如下: 后端使用第三方开源类库Bouncy Castle进行RSA的加解密和生成PEM格 ...
- hihocoder1710 等差子数列
思路: 将数列合并之后使用线段树.边界条件容易写错. 实现: #include <bits/stdc++.h> using namespace std; ; const int INF = ...
- git 恢复误删的文件
误删的文件如何恢复呢? 执行下面的命令: 1. git reset HEAD a.txt 2. git checkout a.txt 注意:上面两个命令,可以帮我们找回删除的文件,但是对文件内容的修改 ...
- oracle 安装,启动 ,plsql 连接
1.下载oracle 服务器端,正常安装,在选择桌面类或者是服务器类的时候选择服务器类. 2.下载oracle 客户端解压版 下载地址 链接:https://pan.baidu.com/s/1mi ...
- ARC(Automatic Reference Counting )技术概述
此文章由Tom翻译,首发于csdn的blog 转自:http://blog.csdn.net/nicktang/article/details/6792972 Automatic Reference ...
- maven多模块项目,多web合并项目使用心得
Fixflow,做中国最好的开源流程引擎!项目地址https://github.com/fixteam/fixflow 此文章适合maven初学者或想接触maven的用户,讲的只是皮毛,高手请自觉略过 ...
- struts2 针对类型转换出错的处理
在类型转换出错时,需要在页面上显示友好提示: 类型转换出错时,会抛出一个运行时异常,程序会根据建立的属性文件,显示相应的错误提示. 实现方法: 1)新建局部属性文件或者全局属性文件 局部属性文件:放置 ...
- vc++实现控制USB设备启用与否
#include <WINDOWS.H> #include <TCHAR.H> #include <SETUPAPI.H> //#in ...
- 02CSS基本语法
CSS基本语法 id选择符 在HTML文档中,需要唯一标识一个元素时,就会赋予它一个id标识,以便在对整个文档进行处理时能够很快地找到这个元素. 而id选择符就是用来对这个单一元素定义单独的样式.#号 ...