【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=3127

【题目大意】

  给出一棵01边权树,求存在多少条路径,使得路径上0和1的数量相同,
  并且在路劲中能找到至少一个中断点,使得分为两段01数量相同的路径

【题解】

  我们对这棵树进行点分治,每次只考虑经过重心的路径,
  我们将路径权值和分出现一次和出现多次进行统计,如果出现一次,
  则在之前出现了多次的权值数组中查相反数,如果出现多次,
  则是一次和多次的权值数组的和,权值和为0的特殊情况则另需考虑以重心为端点的路径。
  每个子树先计算答案,然后统计入权值数组。

【代码】

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int N=200020;
vector<int> v[N],e[N];
typedef long long LL;
const int base=100010;
int n,cnt,root,sum,nowT=0;
int mark[N],T1[N],T2[N],size[N],d[N],dp[N],t[N],vis[N];
LL S1[N],S2[N],ans;
void getroot(int x,int fx){
size[x]=1; dp[x]=0;
for(int i=0;i<v[x].size();i++){
int y=v[x][i];
if(!vis[y]&&y!=fx){
getroot(y,x);
size[x]+=size[y];
dp[x]=max(dp[x],size[y]);
}
}dp[x]=max(dp[x],sum-size[x]);
if(dp[x]<dp[root])root=x;
}
void getdeep(int x,int fx){
if(mark[base+d[x]]){
mark[base+d[x]]++;
if(!d[x])ans++;
if(T2[base+d[x]]==root)S2[base+d[x]]++;
else T2[base+d[x]]=root,S2[base+d[x]]=1;
}else{
mark[base+d[x]]++;
if(T1[base+d[x]]==root)S1[base+d[x]]++;
else T1[base+d[x]]=root,S1[base+d[x]]=1;
}
for(int i=0;i<v[x].size();i++){
int y=v[x][i],w=e[x][i];
if(!vis[y]&&y!=fx){
d[y]=d[x]+w;
getdeep(y,x);
}
}mark[base+d[x]]--;
}
void caldeep(int x,int fx){
if(mark[base-d[x]]){
mark[base-d[x]]++;
if(T2[base-d[x]]==root)ans+=S2[base-d[x]];
else T2[base-d[x]]=root,S2[base-d[x]]=0;
if(T1[base-d[x]]==root)ans+=S1[base-d[x]];
else T1[base-d[x]]=root,S1[base-d[x]]=0;
}else{
mark[base-d[x]]++;
if(T2[base-d[x]]==root)ans+=S2[base-d[x]];
else T2[base-d[x]]=root,S2[base-d[x]]=0;
if(T1[base-d[x]]==root){
if(!d[x])ans+=S1[base-d[x]];
}else T1[base-d[x]]=root,S1[base-d[x]]=0;
}
for(int i=0;i<v[x].size();i++){
int y=v[x][i],w=e[x][i];
if(!vis[y]&&y!=fx){
d[y]=d[x]+w;
caldeep(y,x);
}
}mark[base-d[x]]--;
}
void cal(int x){
for(int i=0;i<v[x].size();i++){
int y=v[x][i],w=e[x][i];
if(!vis[y]){
d[y]=w;
caldeep(y,x);
getdeep(y,x);
}
}
}
void solve(int x){
cal(x); vis[x]=1;
for(int i=0;i<v[x].size();i++){
int y=v[x][i];
if(!vis[y]){
root=0;sum=size[y];
getroot(y,0);
solve(root);
}
}
}
int main(){
while(~scanf("%d",&n)){
ans=0;
for(int i=1;i<=n;i++)v[i].clear(),e[i].clear();
for(int i=1;i<n;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
v[x].push_back(y);
v[y].push_back(x);
e[x].push_back(w?1:-1);
e[y].push_back(w?1:-1);
}memset(vis,0,sizeof(vis));
dp[0]=sum=n;
getroot(1,0);
solve(root);
printf("%lld\n",ans);
}return 0;
}

BZOJ 3127 [Usaco2013 Open]Yin and Yang(树点分治)的更多相关文章

  1. bzoj3127/3697 [Usaco2013 Open]Yin and Yang

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3127 http://www.lydsy.com/JudgeOnline/problem.ph ...

  2. BZOJ 3939 [Usaco2015 Feb]Cow Hopscotch ——线段树 CDQ分治

    显然dp[i][j]=ps[i-1][j-1]-sigma(dp[k<i][l<j],a[i][j]=a[k][l]) 考虑对于每一种颜色都开一颗区间线段树,但是空间不够. 所以我们可以动 ...

  3. 洛谷P3085 [USACO13OPEN]阴和阳Yin and Yang(点分治,树上差分)

    洛谷题目传送门 闲话 偶然翻到一道没有题解的淀粉质,想证明一下自己是真的弱 然而ZSYC(字符串组合)早就切了 然后证明成功了,WA到怀疑人生,只好借着ZSY的代码拍,拍了几万组就出来了... 思路 ...

  4. BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)

    BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...

  5. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  6. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  7. bzoj 4031: 小Z的房间 矩阵树定理

    bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...

  8. [bzoj 3048] [Usaco2013 Jan]Cow Lineup

    [bzoj 3048] [Usaco2013 Jan]Cow Lineup Description 给你一个长度为n(1<=n<=100,000)的自然数数列,其中每一个数都小于等于10亿 ...

  9. [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表)

    [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表) 题面 Byteasar 想在墙上涂一段很长的字符,他为了做这件事从字符的前面一段中截取了一段 ...

随机推荐

  1. Spring 路由地址的基本使用

    1.下面是spring的使用基本框架连接 https://www.cnblogs.com/HD/p/4103239.html

  2. 爬虫--BeautifulSoup

    什么是BeautifulSoup? BeautifulSoup支持的一些解析库 基本使用 from bs4 import BeautifulSoup html =""" ...

  3. 【Python学习】解决pandas中打印DataFrame行列显示不全的问题

    在使用pandas的DataFrame打印时,如果表太长或者太宽会自动只给前后一些行列,但有时候因为一些需要,可能想看到所有的行列. 所以只需要加一下的代码就行了. #显示所有列 pd.set_opt ...

  4. 【Python学习笔记】使用Python计算皮尔逊相关系数

    源代码不记得是哪里获取的了,侵删.此处博客仅作为自己笔记学习. def multipl(a,b): sumofab=0.0 for i in range(len(a)): temp=a[i]*b[i] ...

  5. H5对安卓WeView开发中的影响

     1.body,或者html 高度为100% 会导致下拉直接触发原生的刷新控件,而不是webView滑动到顶部后刷新,以及不会执行onScrollChanged 方法,并且getScrollY 总是返 ...

  6. 基数排序c++实现

    基数排序:是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较.由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数.但在 ...

  7. Swift 特殊关键字 与符号

    #available() 函数来检查API函数的可用性 // 判断当前版本是否 iOS8.0+,OSX10.10+以及以其他平台 if #available(iOS 8.0, OSX 10.10, * ...

  8. SPOJ Two Paths

    Description 给定一个无向图,含有一定的路.从中找出两个最长的路径(每条路径有一些相通路组成)这两个路径不能经过公共的点,求何时二路径的乘积最大. 本题给出的无向图是一棵树,每边权值为1. ...

  9. python_迭代器和生成器

    迭代器和生成器 1.迭代器 特点: 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容 不能随机访问集合中的某个值 ,只能从头到尾依次访问 访问到一半时不能往回退 便于循环比 ...

  10. BNU - 49102

    进化之地(Evoland) Time Limit: 1000ms Case Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO for ...