POJ-1741(树分治)
树的点分治
给出详细的讲解!!点这里打开论文-分治算法在树的路径问题中的应用

本题目是他讲的第一个例题;
我的理解:每次都找树的重心,计算以重心为根的子树之间所贡献的答案。不断这样下去;如果这棵树是一条链,那么就和快排,归并的线性分治法一样了。如果不是一条链那么就相当于,选中一个点,标记为使用过。然后树会被这个节点划分成多棵子树。然后这样分治下去。思想好理解。但是代码不是很好想!详见注解。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long int LL;
const int maxn=20000+100;
struct Node
{
int to,val,next;
}edge[maxn];
int first[maxn],sz,ans,idx,root,n,k;
bool vis[maxn];
/* ----------------------*/
/**
* 邻接表部分
*/
void init()
{
memset(first,-1,sizeof(first));
memset(vis,0,sizeof(vis));
sz=0;
}
void addedge(int s,int t,int val)
{
edge[sz].val=val,edge[sz].to=t,edge[sz].next=first[s];
first[s]=sz++;
}
/*****
* mi,用来找树的重心的时候作比较用的;
* mx[i]数组 代表i节点的子树中最大的size;
* size[i]代表i节点的子树的节点数量;
* dis[i]代表i好节点到根的深度;
* ****************************/
int mi,mx[maxn],size[maxn],dis[maxn];
void dfssize(int x,int pre) //x节点这个子树求size,mx;
{
size[x]=1;
mx[x]=0;
for(int i=first[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to,val=edge[i].val;
if(to!=pre&&!vis[to])
{
dfssize(to,x);
size[x]+=size[to];
if(size[to]>mx[x]) mx[x]=size[to];
}
}
}
void dfsroot(int rt,int x,int pre) //找rt这个 子树的重心
{
mx[x]=max(mx[x],size[rt]-size[x]);
if(mx[x]<mi) mi=mx[x],root=x;
for(int i=first[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to!=pre&&!vis[to]) dfsroot(rt,to,x);
}
}
void dfsdis(int x,int pre,int dd) //计算子树 x的 dis 数组;
{
dis[idx++]=dd;
for(int i=first[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to,val=edge[i].val;
if(to!=pre&&!vis[to]) dfsdis(to,x,dd+val);
}
}
/**
* 计算 F(x)=(子树x的 depth(i)+depth(j)<=k 的对数;)
* calc(x,d);当d=0;返回的是x这颗子树F(x),
* 等d=某条边权值,calc(x,d) 返回值代表子树之间的F(x)
*/
int calc(int x,int d)
{
int res=0;
idx=0;
dfsdis(x,x,d);
sort(dis,dis+idx);
int i=0,j=idx-1;
while(i<j)
{
while(dis[i]+dis[j]>k&&i<j) j--;
res+=j-i;
i++;
}
return res;
}
void dfs(int x)
{
mi=n;
dfssize(x,x);
dfsroot(x,x,x);
ans+=calc(root,0);//当前节点
vis[root]=1;
for(int i=first[root];i!=-1;i=edge[i].next)
{
int to=edge[i].to,val=edge[i].val;
if(!vis[to])
{
ans-=calc(to,val);//减去当前节点的子树之间的
// printf(">> calc=%d\n",calc(root,val));
dfs(to);
}
}
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==0&&k==0) break;
init();
for(int i=1;i<n;i++)
{
int x,y,val;
scanf("%d%d%d",&x,&y,&val);
addedge(x,y,val);
addedge(y,x,val);
}
ans=0;
dfs(1);
printf("%d\n",ans);
}
return 0;
}
POJ-1741(树分治)的更多相关文章
- POJ 1741 树分治
题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...
- poj 1741 树的点分治(入门)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 18205 Accepted: 5951 Description ...
- poj 1741 树的分治
思路:这题我是看 漆子超<分治算法在树的路径问题中的应用>写的. 附代码: #include<iostream> #include<cstring> #includ ...
- POJ 1741 树的点分治
题目大意: 树上找到有多少条路径的边权值和>=k 这里在树上进行点分治,需要找到重心保证自己的不会出现过于长的链来降低复杂度 #include <cstdio> #include & ...
- POJ 1741 [点分治][树上路径问题]
/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给一棵有n个节点的树,每条边都有一个正权值,求一共有多少个点对使得它们之间路的权值和小于给定的k. 思路: <分治算法在树的路径问题中的应用 ...
- [八分之三的男人] POJ - 1741 点分治 && 点分治笔记
题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...
- POJ 1741 点分治
方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- poj 1741 Tree(树的点分治)
poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
- POJ 1741 Tree【树分治】
第一次接触树分治,看了论文又照挑战上抄的代码,也就理解到这个层次了.. 以后做题中再慢慢体会学习. 题目链接: http://poj.org/problem?id=1741 题意: 给定树和树边的权重 ...
随机推荐
- 从零开始学android -- notification通知
目前有三种通知 第一种是普通通知 看看效果 布局什么的太简单了我就不放在上面了给你们看核心的代码就行了 里面的 int notificationID = 1; //设置点击通知后的意图 Inten ...
- git入门四(分支创建合并)
熟悉git分支的原理是掌握了git的精髓,因为git和我们常用的源码管理系统有很大的区别和优点在分支上可以体现出来,一般我们常用的源码管理系统分支都是需要创建新目录,有全新的源码copy,一般都需要创 ...
- Shader 结构体中语义的理解
Shader编写通常会遇到语义 1 float4 vert(float4:POSITION):SV_POSITION 2 { 3 return mul(UNITY_MATRIX_MVP,v); 4 } ...
- 使用 Xcode 5 生成和使用静态库
本文转载至 http://blog.csdn.net/qq331436155/article/details/18363267 静态库Static Libraryiosxcode 在项目中 ...
- 【BZOJ2337】[HNOI2011]XOR和路径 期望DP+高斯消元
[BZOJ2337][HNOI2011]XOR和路径 Description 题解:异或的期望不好搞?我们考虑按位拆分一下. 我们设f[i]表示到达i后,还要走过的路径在当前位上的异或值得期望是多少( ...
- 记录-springMVC访问web-inf下文件问题+在jsp页面导入jquery插件路径不对问题
环境:spring + springMvc + mybatis + maven 关于在springMVC环境访问web-inf目录下文件,其一有在springMVC xml文件下加 <!-- 对 ...
- 解决 SVN版本冲突
链接:http://blog.csdn.net/windone0109/article/details/4857044 版本冲突原因: 假设A.B两个用户都在版本号为100的时候,更新了kingtun ...
- mybatis相关
1 namespace dao中使用namespace+id一起来完成对mapper中sql statement的调用. 2 关于resultMap和parameterType parameterTy ...
- 阿里云+LAMP环境配置
1. 准备好一键Linux环境的脚本: http://dwz.cn/6Nlexm 2. 运行命令:# yum install lynx tree nmap sysstat lrzsz dos2unix ...
- 监听并保存ssh账号密码
有时候渗透搞下一台服务器的权限,想通过此服务器抓取其他服务器的ssh密码.就可以用以下方法,如果管理员通过这台服务器作为跳板登录其他服务器,密码就会记录下来. alias ssh='strace -o ...