BZOJ1468: Tree & BZOJ3365: [Usaco2004 Feb]Distance Statistics 路程统计
【传送门:BZOJ1468&BZOJ3365】
简要题意:
给出一棵n个点的树,和每条边的边权,求出有多少个点对的距离<=k
题解:
点分治模板题
点分治的主要步骤:
1、首先选取一个点,把无根树变成有根树。 那么如何选点呢? ——树形DP
因为树是递归定义的,所以我们当然希望递归的层数最小。 每次选取的点,要保证与此点相连的结点数最多的连通块的结点数最小,我们把这个点叫做“重心”
那么找到一颗树的重心有以下算法:
(1)dfs一次,算出以每个点为根的子树大小
(2)记录以每个结点为根的最大子树的大小
(3)判断:如果以当前结点为根的最大子树大小比当前根更优,更新当前根
2、处理联通块中通过根结点的路径
3、标记根结点(相当于处理过后,将根结点从子树中删除)
4、递归处理以当前点的儿子为根的每棵子树
参考代码(一):
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
int x,y,d,next;
}a[];int len,last[];
void ins(int x,int y,int d)
{
len++;
a[len].x=x;a[len].y=y;a[len].d=d;
a[len].next=last[x];last[x]=len;
}
int tot[],root,sum,ms[];
bool v[];
void getroot(int x,int fa)
{
tot[x]=;ms[x]=;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&v[y]==false)
{
getroot(y,x);
tot[x]+=tot[y];
ms[x]=max(ms[x],tot[y]);
}
}
ms[x]=max(ms[x],sum-tot[x]);
if(ms[root]>ms[x]) root=x;
}
int dep[],id;
int dd[];
void getdep(int x,int fa)
{
dep[++id]=dd[x];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&v[y]==false)
{
dd[y]=dd[x]+a[k].d;
getdep(y,x);
}
}
}
int ans=;
int k;
int cal(int x,int d)
{
dd[x]=d;id=;
getdep(x,);
sort(dep+,dep+id+);
int l=,r=id,c=;
while(l<r)
{
if(dep[l]+dep[r]<=k){c+=r-l;l++;}
else r--;
}
return c;
}
void solve(int x)
{
ans+=cal(x,);
v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(v[y]==false)
{
ans-=cal(y,a[k].d);
sum=tot[y];
root=;getroot(y,x);
solve(root);
}
}
}
int main()
{
int n;
scanf("%d",&n);
len=;memset(last,,sizeof(last));
for(int i=;i<n;i++)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
ins(x,y,d);ins(y,x,d);
}
scanf("%d",&k);
memset(v,false,sizeof(v));
ans=;
sum=tot[]=n;
ms[]=<<-;
root=;getroot(,);
solve(root);
printf("%d\n",ans);
return ;
}
参考代码(二):
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
int x,y,d,next;
}a[];int len,last[];
void ins(int x,int y,int d)
{
len++;
a[len].x=x;a[len].y=y;a[len].d=d;
a[len].next=last[x];last[x]=len;
}
int tot[],root,sum,ms[];
bool v[];
void getroot(int x,int fa)
{
tot[x]=;ms[x]=;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&v[y]==false)
{
getroot(y,x);
tot[x]+=tot[y];
ms[x]=max(ms[x],tot[y]);
}
}
ms[x]=max(ms[x],sum-tot[x]);
if(ms[root]>ms[x]) root=x;
}
int dep[],id;
int dd[];
void getdep(int x,int fa)
{
dep[++id]=dd[x];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa&&v[y]==false)
{
dd[y]=dd[x]+a[k].d;
getdep(y,x);
}
}
}
int ans=;
int k;
int cal(int x,int d)
{
dd[x]=d;id=;
getdep(x,);
sort(dep+,dep+id+);
int l=,r=id,c=;
while(l<r)
{
if(dep[l]+dep[r]<=k){c+=r-l;l++;}
else r--;
}
return c;
}
void solve(int x)
{
ans+=cal(x,);
v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(v[y]==false)
{
ans-=cal(y,a[k].d);
sum=tot[y];
root=;getroot(y,x);
solve(root);
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
len=;memset(last,,sizeof(last));
for(int i=;i<=m;i++)
{
int x,y,d;char st[];
scanf("%d%d%d%s",&x,&y,&d,st+);
ins(x,y,d);ins(y,x,d);
}
scanf("%d",&k);
memset(v,false,sizeof(v));
ans=;
sum=tot[]=n;
ms[]=<<-;
root=;getroot(,);
solve(root);
printf("%d\n",ans);
return ;
}
BZOJ1468: Tree & BZOJ3365: [Usaco2004 Feb]Distance Statistics 路程统计的更多相关文章
- BZOJ_3365_[Usaco2004 Feb]Distance Statistics 路程统计&&POJ_1741_Tree_点分治
BZOJ_3365_[Usaco2004 Feb]Distance Statistics 路程统计&&POJ_1741_Tree_点分治 Description 在得知了自己农 ...
- bzoj 3365 [Usaco2004 Feb]Distance Statistics 路程统计(点分治,单调)
[题意] 求树上长度不超过k的点对数目. [思路] 和 Tree 一样一样的. 就是最后统计的时候别忘把根加上. [代码] #include<set> #include<cmath& ...
- 【刷题】BZOJ 3365 [Usaco2004 Feb]Distance Statistics 路程统计
Description 在得知了自己农场的完整地图后(地图形式如前三题所述),约翰又有了新的问题.他提供 一个整数K(1≤K≤109),希望你输出有多少对农场之间的距离是不超过K的. Input 第1 ...
- BZOJ 3365: [Usaco2004 Feb]Distance Statistics 路程统计
Description 一棵树,统计距离不大于 \(k\) 的点对个数. Sol 点分治. 发现自己快把点分治忘干净了... 找重心使所有儿子的最大值尽量小,然后每次处理全部子树,再减去每个子树的贡献 ...
- bzoj 3365: [Usaco2004 Feb]Distance Statistics 路程统计【容斥原理+点分治】
统计在一个root下的两个子树,每个子树都和前面的运算一下再加进去对于这种需要排序的运算很麻烦,所以考虑先不去同子树内点对的算出合法点对个数,然后减去每一棵子树内的合法点对(它们实际上是不合法的,相当 ...
- BZOJ 3364: [Usaco2004 Feb]Distance Queries 距离咨询
Description 一棵树,询问两点间距离. Sol 倍增. 方向没用. 没有然后了. Code /************************************************ ...
- 【点分治】poj1741 Tree / poj2114 Boatherds / poj1987 Distance Statistics
三道题都很类似.给出1741的代码 #include<cstdio> #include<algorithm> #include<cstring> using nam ...
- LCA【bzoj3364】 [Usaco2004 Feb]Distance Queries 距离咨询
Description 奶牛们拒绝跑马拉松,因为她们悠闲的生活无法承受约翰选择的如此长的赛道.因此约翰决心找一条更合理的赛道,他打算咨询你.此题的地图形式与前两题相同.但读入地图之后,会有K个问题. ...
- POJ1741 Tree + BZOJ1468 Tree 【点分治】
POJ1741 Tree + BZOJ1468 Tree Description Give a tree with n vertices,each edge has a length(positive ...
随机推荐
- 5种语言混合编程:C++、JS、python、Lisp、汇编
/* 混合C++.JS.python.Lisp.汇编 1种语言,5种语法 */ main { //C++ vector<int> v; v.push(2); putsl(v.size()) ...
- 公布自己的pods到CocoaPods trunk 及问题记录
这两天准备把之前写的一些小玩意加入到pods库中去,參考了一些资料后进行操作,实际中也遇到了一些问题,记录下来.问题及解决方案在后面. 參考内容转载例如以下: 首先更新了用trunk之后,CocoaP ...
- 使用XMLHttpRequest解析json
不适用内函数或者promise的方式,可以在外部提取到json数据 <!DOCTYPE html> <html lang="en"> <head> ...
- Nginx访问VM虚拟机CentOS 7系统与本地Windows系统共享目录403
用VMware安装了CentOS7系统,并搭建了Nginx,MySQL,PHP的web项目运行环境,为了方便Windows本地主机进行程序调试把Windows本地项目目录共享到了虚拟机CentOS中的 ...
- Mysql实战45讲 04讲深入浅出索引(上)读书笔记 极客时间
极客时间 Mysql实战45讲 04讲深入浅出索引 极客时间(上)读书笔记 笔记体悟 1.索引的作用:提高数据查询效率2.常见索引模型:哈希表.有序数组.搜索树3.哈希表:键 - 值(key - v ...
- 关于hexo markdown添加的图片在github page中无法显示的问题
title: 关于hexo markdown添加的图片在github page中无法显示的问题 date: 2018-03-31 00:21:18 categories: methods tags: ...
- spark集群体系结构
- Devexpress控件使用一:GridControl
1.控件及列表展示 1).控件 2).构建表格,用于列表展示 3).gridControl绑定数据 4).调用绑定:BindDataSource(InitDt()); 5).展示列表 2.表格的列配置 ...
- mybastis_20190323
1 数据表 items.user.orders.orderdetail user id,username,birthday,sex,address; 使用原生态的jdbc的问题总结? 1 数据库链接问 ...
- ZOJ 2883 Shopaholic【贪心】
解题思路:给出n件物品,每买三件,折扣为这三件里面最便宜的那一件即将n件物品的价值按降序排序,依次选择a[3],a[6],a[9]----a[3*k] Shopaholic Time Limit: 2 ...