BZOJ1468: Tree
时间:2022-05-08
本文章向大家介绍BZOJ1468: Tree,主要内容包括Description、Input、Output、Sample Input、Sample Output、HINT、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
Description
给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K
Input
N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k
Output
一行,有多少对点之间的距离小于等于k
Sample Input
7 1 6 13 6 3 9 3 5 7 4 1 3 2 4 20 4 7 2 10
Sample Output
5
HINT
点分治,真是个神奇的东西。
对于这个题而言,求出所有的距离,再利用双指针法统计答案
具体来说就是记录两个变量,当统计出一个点到其他点的距离时
如果到l+到r的距离是满足条件的,那么l-r中间的点就都满足条件
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e6+10;
const int INF=1e7+10;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
return x*f;
}
struct node
{
int u,v,w,nxt;
}edge[MAXN];
int head[MAXN];
int num=1;
inline void AddEdge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].w=z;
edge[num].nxt=head[x];
head[x]=num++;
}
int K,F[MAXN],siz[MAXN],root,sum,vis[MAXN],tot[MAXN],cnt,deep[MAXN],ans=0;
void GetRoot(int now,int fa)
{
siz[now]=1;
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
if(edge[i].v==fa||vis[edge[i].v]) continue;
GetRoot(edge[i].v,now);
siz[now]+=siz[edge[i].v];
F[now]=max(F[now],siz[edge[i].v]);
}
F[now]=max(F[now],sum-siz[now]);
if(F[now]<F[root]) root=now;
}
void GetDeep(int now,int fa)
{
tot[++cnt]=deep[now];
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
if(vis[edge[i].v]||edge[i].v==fa) continue;
deep[edge[i].v]=deep[now]+edge[i].w;
GetDeep(edge[i].v,now);
}
}
int Calc(int now,int val)//now点满足条件的个数
{
cnt=0;deep[now]=val;//一个小技巧
GetDeep(now,0);
sort(tot+1,tot+cnt+1);
int l=1,r=cnt,NowAns=0;
while(l<r)
{
if(tot[l]+tot[r]<=K) NowAns+=r-l,l++;
else r--;
}
return NowAns;
}
void Solve(int now)
{
vis[now]=1;//别忘了打标记
ans+=Calc(now,0);
for(int i=head[now];i!=-1;i=edge[i].nxt)
{
if(vis[edge[i].v]) continue;
ans-=Calc(edge[i].v,edge[i].w);
sum=siz[edge[i].v];
root=0;
GetRoot(edge[i].v,0);
Solve(edge[i].v);
}
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-1,sizeof(head));
int N=read();
for(int i=1;i<=N-1;i++)
{
int x=read(),y=read(),z=read();
AddEdge(x,y,z);
AddEdge(y,x,z);
}
K=read();
F[0]=INF;sum=N;
//这里有个技巧,把root设置为0,f[0]=INF,那么可以解决找重心时的边界问题
GetRoot(1,0);
Solve(root);
printf("%d",ans);
return 0;
}
- 零基础学编程024:如何快速学会SQL?
- 机器学习的基础讲解:神经网络
- 零基础学编程023:用with实现优雅地释放资源
- Start transaction not working with Revit 2014
- 零基础学编程034:解决一个pandas问题
- ShellExecute 启动外部程序 参数详细介绍
- 零基础学编程033:字符串的split拆分与join连接
- 零基础学编程032:生成二维码
- C#,一些非常简单但应该知道的知识点
- C#神奇的扩展方法
- 使用Python制作一个简单的刷博器
- 零基础学编程031:Python与其它语言最不同的一条语法规则
- dedecms批量导出新增文章url和标题
- 明理知意:复合索引优化及索引访问原理
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法