bzoj3697
一开始又看错题,以为同样路径上不同的休息站是算不同路径,后来发现休息站只是路径合法的条件
毫无疑问是树的分治,下面我们只要考虑计算能建休息站的路径
我们把阳看作路径权值为1,阴作为路径权值-1
点分治之后,休息站的建立只有三种情况,在根,在之前的子树路径上,在现在的子树路径上
我们先考虑休息站在根到子树的路径上,我们设d[x]表示点x到根的路径距离
能建也就是说在x到根的路径上存在一点y,d[y]=d[x],也就是当前距离之前是否出现过,打个标记即可
然后我们只要分别记录一下当前由根出发路径和为x,能否在这条路径上建休息站的路径数目就很容易统计了
注意一些地方的漏算和重复计算
type node=record
po,next,num:longint;
end; var w,g:array[-..,..] of int64;
s,p,f,d:array[..] of longint;
v:array[..] of boolean;
can:array[-..] of longint;
e:array[..] of node;
l,r,root,len,i,x,tot,y,z,n:longint;
ans:int64; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure add(x,y,z:longint);
begin
inc(len);
e[len].po:=y;
e[len].num:=z;
e[len].next:=p[x];
p[x]:=len;
end; procedure getroot(x,fa:longint);
var i,y:longint;
begin
i:=p[x];
s[x]:=;
f[x]:=;
while i<> do
begin
y:=e[i].po;
if not v[y] and (y<>fa) then
begin
getroot(y,x);
s[x]:=s[x]+s[y];
f[x]:=max(f[x],s[y]);
end;
i:=e[i].next;
end;
f[x]:=max(f[x],tot-s[x]);
if f[x]<f[root] then root:=x;
end; procedure dfs(x,fa:longint);
var i,y:longint;
begin
if can[d[x]]> then
begin
inc(g[d[x],]);
ans:=ans+w[-d[x],]+w[-d[x],];
end
else begin
inc(g[d[x],]);
ans:=ans+w[-d[x],];
end;
inc(can[d[x]]);
r:=max(r,d[x]);
if l>d[x] then l:=d[x];
i:=p[x];
while i<> do
begin
y:=e[i].po;
if not v[y] and (y<>fa) then
begin
d[y]:=d[x]+e[i].num;
dfs(y,x);
end;
i:=e[i].next;
end;
dec(can[d[x]]);
end; procedure work(x:longint);
var i,y,j:longint;
begin
v[x]:=true;
i:=p[x];
l:=; r:=;
w[,]:=; //注意根节点可以作为终点
while i<> do
begin
y:=e[i].po;
if not v[y] then
begin
d[y]:=e[i].num;
dfs(y,x);
ans:=ans+(w[,]-)*g[,]; //注意当前子树内不能建休息站且路径和为0可以和之前的子树内(不包括单独根节点)这样的路径组成合法路径(根节点是休息站),而之前的计算我们是没有算进去的
for j:=l to r do
begin
w[j,]:=w[j,]+g[j,]; //更新
w[j,]:=w[j,]+g[j,];
g[j,]:=; g[j,]:=;
end;
end;
i:=e[i].next;
end;
for j:=l to r do
begin
w[j,]:=;
w[j,]:=;
end;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if not v[y] then
begin
root:=;
tot:=s[y];
getroot(y,);
work(root);
end;
i:=e[i].next;
end;
end; begin
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;
f[]:=n+;
tot:=n;
len:=;
getroot(,);
work(root);
writeln(ans);
end.
bzoj3697的更多相关文章
- 【BZOJ3697】采药人的路径 点分治
[BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是 ...
- 【BZOJ3697】采药人的路径(点分治)
题意:采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径是很 ...
- [bzoj3697]采药人的路径_点分治
采药人的路径 bzoj-3697 题目大意:给你一个n个节点的树,每条边分为阴性和阳性,求满足条件的链的个数,使得这条链上阴性的边的条数等于阳性的边的条数,且这条链上存在一个节点,这个节点到一个端点的 ...
- 【BZOJ-3697&3127】采药人的路径&YinandYang 点分治 + 乱搞
3697: 采药人的路径 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 681 Solved: 246[Submit][Status][Discus ...
- BZOJ3697: 采药人的路径
传送门 不是那么裸的点分治. $f[i][0/1]$表示当前节点的一个子树中总权值和为$i$,且是否存在一个前缀使得其前缀和为$i$ $g[i][0/1]$表示当前节点的已遍历过的子树,其余一样. 对 ...
- 【BZOJ3697】采药人的路径
题解: 比较简单的点分治 首先暴力的话直接枚举 然后枚举另一个点的时候顺便看一下有没有零点 n^2 考虑点分治 分治之后用f[i][0/1]表示权值为i,有没有零点的方案数 我们来证明一件事情,如果两 ...
- BZOJ3697采药人的路径——点分治
题目描述 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径 ...
- 2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...
- bzoj千题计划248:bzoj3697: 采药人的路径
http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...
随机推荐
- Mysql 的函数
函数 MySQL函数分为系统函数与自定义函数 系统函数: pow(m,n) 求m的n次方 rand() 随机获取0至1之间的小数 floor(); ...
- php嵌入html的解析过程
php嵌入html的解析过程 示例: 执行过程: 首先明确:PHP是分段读取一次执行(编译),JS是分段读取分段执行 程序就是对内存的操作 函数可以先调用后定义,原因,程序的执行时 ...
- QT宏 Q_OBJECT,explicit, QHostAddress, quint, emit
QT相關 一. 參考: 1.宏Q_OBJECT 二. explicit struct constrcution 三. QHostAddress Detailed Description: The QH ...
- php 调用 webservice服务
class data{ $a = 123; $b = 456; } //直接php的SoapClient类 $client = new SoapClient('http://xxx.com/xx.as ...
- WIN7中oracle10g的安装注意事项
1.本次安装数据库版本为10.2.0.1,操作系统版本为windows7 32位 2.注意在"setup.exe"中以右键属性后,设置以兼容模式及以管理员身份运行该程序:在%安装文 ...
- Python3 IO
在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中 ...
- opensuse13.1 双屏幕扩展
最近搞一项j2eeweb工程,想要使用Linux平台编写程序.对比Ubuntu 14.04.Redhat.openSUSE,选择了最后这个. 安装的时候将/boot只分了100M,后来空间不足软件都安 ...
- C#实现登录窗口(不用隐藏)
C#登录窗口的实现,特点就是不用隐藏,感兴趣的朋友不要错过 (1).在程序入口处,打开登录窗口 复制代码代码如下: static void Main() { Application.EnableV ...
- wpf单实例运行
默认情况下我们可以打开一个应用程序多个实例,例如你双击一个exe多次.当然有些时候这么做会带来很多好处,但是有时我们又不希望这么做,要避免这个问题其实很简单,同WinForm中单实例运行一个应用是一样 ...
- MVC去掉传参时的验证:从客户端中检测到有潜在危险的Request.QueryString值
解决方法:给Action添加属性[ValidateInput(false)]. 例: [ValidateInput(false)] public ActionResult Index(string o ...