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

解题思路:

点分治要求在寻找到一条链时统计答案与重心在链的哪个位置无关。而显然这道题如果枚举重心为中转站是错误的,因为一条链只被统计一次,而中心位置很可能是错误的,所以我们需要修正这一点,就是统计重心路径上可能出现的中心位置。

换句话说,开四个桶来记录,分别记录当前子树内可能出现的中转站(出现过的距离重复,在差分的意义下说明出现和为0的区间),另外一个就是之前子树的答案,每次更新完合并桶就好了。

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const int N=;
struct pnt{
int hd;
int dis;
int wgt;
bool vis;
}p[N];
struct ent{
int twd;
int lst;
int vls;
}e[N<<];
lnt f[N<<][],g[N<<][];
int has[N<<];
int n;
lnt top;
int cnt;
lnt ans;
int lim;
int size;
int root;
int maxsize;
void ade(int f,int t,int v)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
e[cnt].vls=v;
p[f].hd=cnt;
return ;
}
void grc_dfs(int x,int f)
{
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f||p[to].vis)
continue;
grc_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(p[to].wgt>maxs)
maxs=p[to].wgt;
}
if(maxs<size-p[x].wgt)
maxs=size-p[x].wgt;
if(maxs<maxsize)
{
maxsize=maxs;
root=x;
}
return ;
}
void ans_dfs(int x,int fa,int dep)
{
lim=std::max(lim,dep);
if(has[p[x].dis])
f[p[x].dis][]++;
else
f[p[x].dis][]++;
has[p[x].dis]++;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==fa||p[to].vis)
continue;
p[to].dis=p[x].dis+e[i].vls;
ans_dfs(to,x,dep+);
}
has[p[x].dis]--;
return ;
}
void bin_dfs(int x)
{
int maxd=;
p[x].vis=true;
g[n][]=;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].vis)
continue;
p[to].dis=n+e[i].vls;
lim=;
ans_dfs(to,to,);
maxd=std::max(maxd,lim);
ans+=f[n][]*(g[n][]-);
for(int j=-lim;j<=lim;j++)
ans+=g[n-j][]*f[n+j][]+g[n-j][]*f[n+j][]+g[n-j][]*f[n+j][];
for(int j=n-lim;j<=n+lim;j++)
{
g[j][]+=f[j][];
g[j][]+=f[j][];
f[j][]=f[j][]=;
}
}
for(int i=n-maxd;i<=n+maxd;i++)
g[i][]=g[i][]=;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].vis)
continue;
root=;
size=p[to].wgt;
maxsize=0x3f3f3f3f;
grc_dfs(to,to);
bin_dfs(root);
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
c=c*-;
ade(a,b,c);
ade(b,a,c);
}
root=;
size=n;
maxsize=0x3f3f3f3f;
grc_dfs(,);
bin_dfs(root);
printf("%lld\n",ans);
return ;
}

BZOJ3697: 采药人的路径(点分治)的更多相关文章

  1. BZOJ3697采药人的路径——点分治

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

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

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

  3. [bzoj3697]采药人的路径——点分治

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

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

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

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

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

  6. bzoj千题计划248:bzoj3697: 采药人的路径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3697 点分治 路径0改为路径-1 g[i][0/1] 和 f[i][0/1]分别表示当前子树 和 已 ...

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

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

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

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

  9. BZOJ 3697/3127 采药人的路径 (点分治)

    题目大意: 从前有一棵无向树,树上边权均为$0$或$1$,有一个采药人,他认为如果一条路径上边权为$0$和$1$的边数量相等,那么这条路径阴阳平衡.他想寻找一条合法的采药路径,保证阴阳平衡.然后他发现 ...

随机推荐

  1. EventBus框架原理解析(结合源代码)(上)

    上一篇文章http://blog.csdn.net/crazy__chen/article/details/47425779 和大家一起模仿EventBus的实现机制.和大家一起写出了一个简易的Eve ...

  2. 关于android studio几种常见的错误解决

    我也是从ec转到as的,没办法,大势所趋嘛,然而,在使用as的过程中遇到了非常多匪夷所思的错误,如今就说一下今天我遇到的这个错误. 美工妹子给了我一张图片,用来当做button的背景图,当然,这个图也 ...

  3. 关于commJS 和 es6 的一些区别

    CommonJS模块与ES6模块的区别 本文转自 https://www.cnblogs.com/unclekeith/archive/2017/10/17/7679503.html CommonJS ...

  4. Linux安全应用之防垃圾邮件服务器的构建

    Linux安全应用之防垃圾邮件服务器的构建 一.垃圾邮件产生的原因 垃圾邮件(SPAM) 也称作UCE(Unsoticited Commercial Email.未经许可的商业电子邮件)或UBE(Un ...

  5. Android studio 导入PullToRefresh

    1.新建一个Android项目,下载好Android-PullToRefresh-master,并解压,找到library文件夹,我把他放在C:\import目录下,下面的都是根据箭头一步一步的点击即 ...

  6. sql中 where语句的用法

    //查询user_id 10到20 之间  30到40之间 //查询user_id 不在10到20之间的

  7. vue.js路由vue-router(一)——简单路由基础

    前言 vue.js除了拥有组件开发体系之外,还有自己的路由vue-router.在没有使用路由之前,我们页面的跳转要么是后台进行管控,要么是用a标签写链接.使用vue-router后,我们可以自己定义 ...

  8. WebAssembly学习(三):AssemblyScript - TypeScript到WebAssembly的编译

    虽然说只要高级语言能转换成 LLVM IR,就能被编译成 WebAssembly 字节码,官方也推荐c/c++的方式,但是让一个前端工程师去熟练使用c/c++显然是有点困难,那么TypeScript ...

  9. 洛谷—— P1328 生活大爆炸版石头剪刀布

    https://www.luogu.org/problem/show?pid=1328 题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在< ...

  10. 49.Node.js RESTful API

    转自:http://www.runoob.com/nodejs/nodejs-express-framework.html 什么是 REST? REST即表述性状态传递(英文:Representati ...