POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量
| Time Limit: 1000MS | Memory Limit: 30000K | |
| Total Submissions: 34141 | Accepted: 11420 |
Description
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The last test case is followed by two zeros.
Output
Sample Input
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output
8
题意就是给你一个带边权的树,求树上最短距离<=K的点对数量。树分治模板题。
代码:
//树分治-点分治
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int inf=1e9+;
const int maxn=1e5+; int head[maxn],tot;
int root,allnode,ans,n,k;
int vis[maxn],deep[maxn],dis[maxn],siz[maxn],point[maxn];//deep[0]子节点个数(路径长度),point为重心节点 struct node{
int to,next,val;
}edge[maxn<<]; void add(int u,int v,int w)//前向星存图
{
edge[tot].to=v;
edge[tot].next=head[u];
edge[tot].val=w;
head[u]=tot++;
} void init()//初始化
{
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
tot=;
} void get_root(int u,int father)//重心
{
siz[u]=;point[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
get_root(v,u);//递归得到子树大小
siz[u]+=siz[v];
point[u]=max(point[u],siz[v]);//更新u节点的point
}
point[u]=max(point[u],allnode-siz[u]);//保存节点size
if(point[u]<point[root]) root=u;//更新当前子树的重心
} void get_dis(int u,int father)//获取子树所有节点与根的距离
{
deep[++deep[]]=dis[u];
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
int w=edge[i].val;
dis[v]=dis[u]+w;
get_dis(v,u);
}
} int cal(int u,int now)
{
dis[u]=now;deep[]=;
get_dis(u,);
sort(deep+,deep+deep[]+);
int all=;
for(int l=,r=deep[];l<r;){//二分
if(deep[l]+deep[r]<=k){
all+=r-l;l++;
}
else r--;
}
return all;
} void solve(int u)//以u为重心进行计算
{
ans+=cal(u,);//以当前u为重心的贡献
vis[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]) continue;
ans-=cal(v,edge[i].val);//减去子树的影响
allnode=siz[v];
root=;
get_root(v,u);
solve(root);
}
} int main()
{
while(~scanf("%d%d",&n,&k)&&n&&k){
init();
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
root=ans=;
allnode=n;point[]=inf;
get_root(,);
solve(root);
printf("%d\n",ans);
}
return ;
}
一样的东西,就只是改了一下数据范围和输入格式。
代码:
//树分治-点分治
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int inf=1e9+;
const int maxn=4e4+; int head[maxn],tot;
int root,allnode,ans,n,k;
int vis[maxn],deep[maxn],dis[maxn],siz[maxn],point[maxn];//deep[0]子节点个数(路径长度),point为重心节点 struct node{
int to,next,val;
}edge[maxn<<]; void add(int u,int v,int w)//前向星存图
{
edge[tot].to=v;
edge[tot].next=head[u];
edge[tot].val=w;
head[u]=tot++;
} void init()//初始化
{
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
tot=;
} void get_root(int u,int father)//重心
{
siz[u]=;point[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
get_root(v,u);//递归得到子树大小
siz[u]+=siz[v];
point[u]=max(point[u],siz[v]);//更新u节点的point
}
point[u]=max(point[u],allnode-siz[u]);//保存节点size
if(point[u]<point[root]) root=u;//更新当前子树的重心
} void get_dis(int u,int father)//获取子树所有节点与根的距离
{
deep[++deep[]]=dis[u];
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
int w=edge[i].val;
dis[v]=dis[u]+w;
get_dis(v,u);
}
} int cal(int u,int now)
{
dis[u]=now;deep[]=;
get_dis(u,);
sort(deep+,deep+deep[]+);
int all=;
for(int l=,r=deep[];l<r;){//二分
if(deep[l]+deep[r]<=k){
all+=r-l;l++;
}
else r--;
}
return all;
} void solve(int u)//以u为重心进行计算
{
ans+=cal(u,);//以当前u为重心的贡献
vis[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]) continue;
ans-=cal(v,edge[i].val);//减去子树的影响
allnode=siz[v];
root=;
get_root(v,u);
solve(root);
}
} int main()
{
scanf("%d",&n);
init();
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
scanf("%d",&k);
root=ans=;
allnode=n;point[]=inf;
get_root(,);
solve(root);
printf("%d\n",ans);
return ;
}
POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量的更多相关文章
- POJ1471 Tree/洛谷P4178 Tree
Tree P4178 Tree 点分治板子. 点分治就是直接找树的重心进行暴力计算,每次树的深度不会超过子树深度的\(\frac{1}{2}\),计算完就消除影响,找下一个重心. 所以伪代码: voi ...
- 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)
推荐YCB的总结 推荐你谷ysn等巨佬的详细题解 大致流程-- dfs求出当前树的重心 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成) 容斥减去不合法情况(两条子路径 ...
- 洛谷P4178 Tree (点分治)
题目描述 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K 输入输出格式 输入格式: N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下 ...
- 洛谷 P4178 Tree —— 点分治
题目:https://www.luogu.org/problemnew/show/P4178 这道题要把 dep( dis? ) 加入一个 tmp 数组里,排序,计算点对,复杂度很美: 没有写 sor ...
- 洛谷P4178 Tree (算竞进阶习题)
点分治 还是一道点分治,和前面那道题不同的是求所有距离小于等于k的点对. 如果只是等于k,我们可以把重心的每个子树分开处理,统计之后再合并,这样可以避免答案重复(也就是再同一个子树中出现路径之和为k的 ...
- 2018.07.20 洛谷P4178 Tree(点分治)
传送门 又一道点分治. 直接维护子树内到根的所有路径长度,然后排序+双指针统计答案. 代码如下: #include<bits/stdc++.h> #define N 40005 using ...
- [洛谷P4178]Tree
题目大意:给一棵树,问有多少条路径长度小于等于$k$ 题解:点分治 卡点:无 C++ Code: #include <cstdio> #include <algorithm> ...
- 洛谷 P4178 Tree
#include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #inclu ...
- [洛谷P4178] Tree (点分治模板)
题目略了吧,就是一棵树上有多少个点对之间的距离 \(\leq k\) \(n \leq 40000\) 算法 首先有一个 \(O(n^2)\) 的做法,枚举每一个点为起点,\(dfs\) 一遍可知其它 ...
随机推荐
- 【Maven基础入门】02 了解POM文件构建
温故 上一节我们说过:Maven 是一个基于POM文件的构建工具,当然离不开POM文件 POM文件是一个XML标记语言表示的文件,文件就是:pom.xml 一个POM文件包含了项目的基本信息,用于描述 ...
- win add static arp
win add static arp > arp -s "192.168.0.2" "00-0a-35-01-fe-c0" > arp -a | f ...
- 将windows共享文件夹挂载到Linux
今天想用docker部署下 .net core的 服务,需要把代码文件从windows传到linux,以前一直都是拖拽的,这次安装的系统没有图形界面, 所以到网上找到了下面的这种方法,将共享文件夹挂载 ...
- javascript ~~ 符号是什么意思呢?
~ bitwise NOT 运算符 ~对操作数按位取反,两个的意思即作两次取反操作,其实是等作原数本身(操作数是32整数范围内) ~~(Math.random()*7) 即 var n = Math. ...
- el-table单元格样式更改
前几天遇到一个关于el-table表格样式的问题一直没解决 因为在el-table-column加样式并不生效所以更改起来比较麻烦 后来了看来element官方文档和在一些关于此方面的博客,使用了一个 ...
- echarts统计x轴区间的数值
有时我们需要统计自定义echarts图,统计x轴区间的y轴数量. 思路是利用echarts的自定义配置:option.series[i].type='custom'中的renderItem(param ...
- webpack+vue-cil跨域配置接口地址代理
在vue项目开发的时候,接口联调的时候一般都是同域名下,且不存在跨域的情况下进行接口联调,但是当我们现在使用vue-cli进行项目打包的时候,我们在本地启动服务器后,比如本地开发服务下是 http:/ ...
- mysql配置临时日志(无需重启服务)
use mysql; //指定日志的存储方式 SET GLOBAL log_output = 'TABLE'; //查询日志开启 SET GLOBAL general_log = 'ON'; sele ...
- K9F1G08U0B K9F2G08U0A K9F2G08U0M
*L must be set to "Low" Ax表示bit,分5个周期写,一次一个Byte 原理图 引脚定义 命令 Program Erase Read 实验程序 https: ...
- 构建nodejs环境
总想留下点东西,不负年华! 00.download releasehttps://nodejs.org/dist/ //all release example https://nodejs. ...