传送门

点分治好题。

题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数。


思路:

考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数。

然后发现对于一个点ppp,经过它的这样的路径满足如下至少一个条件:

  1. ∃v\exist v∃v满足dist(v,p)=0&&∃v0∈roadv,pdist(v,p)=0\&\&\exist v_0\in road_{v,p}dist(v,p)=0&&∃v0​∈roadv,p​满足dist(v0,v)=0dist(v_0,v)=0dist(v0​,v)=0
  2. ∃v1,v2\exist v_1,v_2∃v1​,v2​满足$dist(v_1,p)=0,dist(v_2,p)=0
  3. ∃v1,v2\exist v_1,v_2∃v1​,v2​满足dist(v1,p)+dist(v2,p)=0&&∃v0∈roadv1,pdist(v_1,p)+dist(v_2,p)=0\&\&\exist v_0\in road_{v_1,p}dist(v1​,p)+dist(v2​,p)=0&&∃v0​∈roadv1​,p​满足distv0,p=distv1,pdist{v_0,p}=dist_{v_1,p}distv0​,p=distv1​,p​
  4. ∃v1,v2\exist v_1,v_2∃v1​,v2​满足dist(v1,p)+dist(v2,p)=0&&∃v0∈roadv2,pdist(v_1,p)+dist(v_2,p)=0\&\&\exist v_0\in road_{v_2,p}dist(v1​,p)+dist(v2​,p)=0&&∃v0​∈roadv2​,p​满足distv0,p=distv2,pdist{v_0,p}=dist_{v_2,p}distv0​,p=distv2​,p​

然后点分容斥处理即可,注意不要忘记第一种情况的讨论。

代码:

#include<bits/stdc++.h>
#define fi first
#define se second
#define ri register int
using namespace std;
const int N=1e5+5;
int n,siz[N],msiz[N],rt=0,all=0,lim;
bool vis[N];
typedef pair<int,int> pii;
typedef long long ll;
vector<pii>e[N];
ll ans=0,cnt[2][N][2]={0};
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
void findroot(int p,int fa){
	siz[p]=1,msiz[p]=0;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i].fi)==fa||vis[v])continue;
		findroot(v,p),siz[p]+=siz[v],msiz[p]=max(msiz[p],siz[v]);
	}
	msiz[p]=max(msiz[p],all-siz[p]);
	if(msiz[p]<msiz[rt])rt=p;
}
void getdis(int p,int fa,int dist,int down,int up){
	if(dist>=down&&dist<=up){
		if(dist>=0)++cnt[0][dist][1];
		if(dist<0)++cnt[1][-dist][1];
	}
	else{
		if(dist>=0)++cnt[0][dist][0];
		if(dist<0)++cnt[1][-dist][0];
	}
	down=min(down,dist),up=max(up,dist),lim=max(lim,max(-down,up));
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i].fi)==fa||vis[v])continue;
		getdis(v,p,dist+e[p][i].se,down,up);
	}
}
inline void calc(int p,int pre,int tmp){
	ll sum=0;
	lim=0;
	if(tmp==1)getdis(p,0,pre,1,-1);
	else getdis(p,0,pre,0,0);
	sum+=cnt[0][0][1]*(cnt[0][0][1]-1)/2,cnt[0][0][0]=cnt[0][0][1]=0;
	for(ri i=1;i<=lim;++i){
		sum+=cnt[0][i][0]*cnt[1][i][1];
		sum+=cnt[0][i][1]*cnt[1][i][0];
		sum+=cnt[0][i][1]*cnt[1][i][1];
		cnt[0][i][0]=cnt[0][i][1]=cnt[1][i][0]=cnt[1][i][1]=0;
	}
	ans+=sum*tmp;
}
void solve(int p,int fa,int tim,int dist){
	if(!dist){
		if(tim>=2)++ans;
		++tim;
	}
	for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i].fi)!=fa&&!vis[v])solve(v,p,tim,dist+e[p][i].se);
}
void dfs(int p){
	vis[p]=1,solve(p,0,0,0),calc(p,0,1);
	for(ri i=0,v;i<e[p].size();++i){
		if(vis[v=e[p][i].fi])continue;
		calc(v,e[p][i].se,-1),rt=0,all=siz[v],findroot(v,0),dfs(rt);
	}
}
int main(){
	freopen("lx.in","r",stdin);
	n=read();
	for(ri i=1,u,v,w;i<n;++i)u=read(),v=read(),w=read()?1:-1,e[u].push_back(pii(v,w)),e[v].push_back(pii(u,w));
	rt=0,all=n,msiz[rt]=n,findroot(1,0),dfs(rt);
	cout<<ans;
	return 0;
}

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

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

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

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

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

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

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

  4. 2019.01.09 bzoj2599: [IOI2011]Race(点分治)

    传送门 题意:给一棵树,每条边有权.求一条路径,权值和等于K,且边的数量最小. 思路: 考虑点分治如何合并. 我们利用树形dpdpdp求树的直径的方法,边dfsdfsdfs子树边统计答案即可. 代码: ...

  5. AWS re:Invent(2019.01.09)

    时间:2019.01.09地点:北京国际饭店

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

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

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

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

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

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

  9. #学习笔记# VALSE 2019.01.09 朱俊彦 --- Learning to Synthesize Images, Videos, and 3D Objects

    视频类型:VALSE-webinar 报告时间:2019年01月09日 报告人:MIT朱俊彦 报告题目:Learning to Synthesize Images, Videos, and 3D Ob ...

随机推荐

  1. HDU 6214 Smallest Minimum Cut(最少边最小割)

    Problem Description Consider a network G=(V,E) with source s and sink t. An s-t cut is a partition o ...

  2. 面向对象中的property装饰器讲解

    面向对象中可以用property来修饰我们的函数,必须下面的例子 class Test(object): def __init__(self,name): self.name = name @prop ...

  3. xadmin系列之django的url分发的方式

    一.先介绍一下我们自己的urls中是如何进行路由分发的 一.一级路由 urlpatterns = [ url(r'^upload/', views.upload,name="upload&q ...

  4. swift - 听云监测(Testin - Bugout) - 集成

    听云的SDK集成放的太难找了,官方demo到现在也没找到.. 我找了半天没找到在哪,看下面俩链接吧, 切记:添加的三方库 以文档为主,视频里的三方库 不一定正确 iOS SDK 集成:https:// ...

  5. 13-算法训练 P0505

    算法训练 P0505   时间限制:1.0s   内存限制:256.0MB      一个整数n的阶乘可以写成n!,它表示从1到n这n个整数的乘积.阶乘的增长速度非常快,例如,13!就已经比较大了,已 ...

  6. go语言sync包的学习(Mutex、WaitGroup、Cond)

    package main; import ( "fmt" "sync" "runtime" "time" ) //加锁, ...

  7. python re正则

    一:什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 r ...

  8. EmguCV Image类中的函数(二)使用MorphologyEx进行更多的变换

    MorphologyEx中所有的变换如下图所示 调用方法: Mat aaa = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.R ...

  9. URLEncoder.encode转译后“空格”变“加号”的问题的解决方案

    我用dst_fname=URLEncoder.encode(dst_fname);对字符串dst_fname进行编码,但是发现空格全部都变成了加号,我们提需求的傻B非得要空格的,但是不编码有很多非常特 ...

  10. Get、Post 提交的乱码问题

    1.问题 在spring mvc开发的时候出现乱码问题: 2.解决方案 (1)Get提交:tomcat容器接收的造成的乱码问题,修改server.xml文件: (2)Post提交:在web.xml中配 ...