【点分治】poj1741
来源:互联网 发布:数值模拟软件 编辑:程序博客网 时间:2024/04/30 06:23
众所周知,树分治有两种:点分治和边分治。顾名思义,点分治是按点进行分治,为了让子问题的规模尽量小,我们通常选择重心做为分治的点;而边分治通常选择使得所分离出来的两棵子树的结点个数尽量平均的边。求重心和这样的边均可以用树DP的方法解决。通常点分治和边分治的递归层数为
以上均属于扯淡……
关于树的分治有一篇IOI的论文《分治算法在树的路径问题中的应用》,讲得比较详细。
先附上重心的代码
int sz[MAXN], sz2[MAXN], root;void getroot(int u,int fa){ sz[u]=1, sz2[u]=0; for(int p=adj[u], v;~p;p=edge[p].next) if((v=edge[p].v)!=fa) { getroot(v,u); sz[u]+=sz[v]; sz2[u]=max(sz2[u],sz[v]); } sz2[u]=max(sz2[u],sum-sz[u]); if(sz2[u]<sz2[root])root=u;}
1.poj1741
男人八题之一……
题目大意:有一颗节点为
如何用点分治做?
考虑经过点
为了防止退化为一条链,每次分治都以树的重心分治。
现在的问题是如何统计满足上述条件的点对的个数?
别忘了这是一个计数问题。
这里有一个经典的线性扫描的方法。
#include <iostream>#include <cstdio>#include <algorithm>#define max(a,b) ((a)>(b)?(a):(b))#define MAXN 10050using namespace std;int n, k, pos, sum, root, a, b, c;struct node{ int v, w, next;}edge[MAXN<<1];int adj[MAXN], dis[MAXN], ans;bool vis[MAXN];inline void add(int a,int b,int c){ edge[pos].v=b, edge[pos].w=c, edge[pos].next=adj[a]; adj[a]=pos; ++pos;}int sz[MAXN], sz2[MAXN];void getroot(int u,int fa){ //在计算重心的过程中,由于子树大小的变化,所以sz[u],sz2[u]要时时更新 sz[u]=1, sz2[u]=0; for(int p=adj[u], v;~p;p=edge[p].next) //!vis[v]是防止访问到子树以外的节点 if((v=edge[p].v)!=fa&&!vis[v]) { getroot(v,u); sz[u]+=sz[v]; sz2[u]=max(sz2[u],sz[v]); } sz2[u]=max(sz2[u],sum-sz[u]); if(sz2[u]<sz2[root])root=u;}//求出子树中每一个点到重心的距离int d[MAXN], cnt;void getdis(int u,int fa){ d[++cnt]=dis[u]; for(int p=adj[u], v;~p;p=edge[p].next) //!vis[v]是防止访问到子树以外的节点 if((v=edge[p].v)!=fa&&!vis[v]) { dis[v]=dis[u]+edge[p].w; getdis(v,u); }}int cal(int u,int init){ dis[u]=init; cnt=0; getdis(u,0); //排序以进行线性扫描 sort(d+1,d+cnt+1); int l=1, r=cnt, ans=0; while(l<r) if(d[l]+d[r]<=k)ans+=r-l++; else --r; return ans;}void dfs(int u){ vis[u]=1; ans+=cal(u,0); for(int p=adj[u], v;~p;p=edge[p].next) if(!vis[(v=edge[p].v)]) { //对dis[v]赋初值是为了方便计算 //dis(u,v)+2*edge[p].w=dis[u]+edge[p].w+dis[v] ans-=cal(v,edge[p].w); sum=sz[v]; getroot(v,root=0); dfs(root); }}int main(){ while(~scanf("%d%d",&n,&k)&&n+k) { for(int i=1;i<=n;++i)adj[i]=-1, vis[i]=0; pos=ans=0; for(int i=1;i<n;++i) { scanf("%d%d%d",&a,&b,&c); add(a,b,c), add(b,a,c); } sz2[0]=sum=n; getroot(1,root=0); dfs(root); printf("%d\n",ans); } return 0;}
0 0
- 点分治 poj1741
- [Poj1741]Tree (点分治)
- poj1741 树上点分治
- poj1741(点分治)
- poj1741 Tree 点分治
- [POJ1741]Tree |点分治
- POJ1741 点分治
- poj1741 Tree 点分治
- 【poj1741】Tree 点分治
- poj1741 tree 点分治
- 【点分治】poj1741
- 【点分治】poj1741
- 【POJ1741】Tree【点分治】
- poj1741 点分治
- POJ1741 Tree 点分治
- 【poj1741】tree 点分治
- POJ1741点分治
- [POJ1741]Tree-点分治
- BSOJ1125:树Tree 树链剖分 单点修改 区间取反 区间查询
- BSOJ3194:黑白树 树链剖分 TLE90分
- 记一次手贱之旅--Ubuntu安装NVIDIA驱动
- LeetCode 136.137. 260.Single Number ⅠII III
- BSOJ2381:捉迷藏 括号序列 线段树维护
- 【点分治】poj1741
- Android基础:startActivityForResult+onActivityResult+setResult
- 【点分治】poj1741
- 阿里2015实习生招聘前端方向--编程题(2)
- BSOJ2764:树中点对统计 点分治
- 非常全面到位的介绍与源代码地址 :Python 网页爬虫 & 文本处理 & 科学计算 & 机器学习 & 数据挖掘兵器谱
- webrtc学习之旅Getting Started
- Building Maintainable Software-java篇之Keep Architecture Components Balanced
- HttpUrlConnection缓存,仿微信朋友圈图片缓存效果