POJ 1741 Tree 点分治
2016-08-31 15:04
344 查看
时空隧道
题目大意:
给出一棵树,求出这棵树上满足要求的点对有多少个—-要求是两点之间距离小于等于k
分析:
第一想法是n^2暴力,但是很不幸,n<=10000,n^2炸了….
怎么办呢….
我们如果把这棵树看成一棵有根树,那么这些点对有两种情况—-一种是两个点在两棵子树中,一种是在一颗子树中…
所以我们可以求出dis[i](所有点到重心的距离—为什么是重心呢…防止退化成n^2),然后在dis数组中On的求出满足要求的点对,然后递归处理它的子树,但是这样会有重复的,所以要减去子树中的ans,也就是说只有路径经过重心的点对才会对答案有贡献
代码如下:
by >_< neighthorn
题目大意:
给出一棵树,求出这棵树上满足要求的点对有多少个—-要求是两点之间距离小于等于k
分析:
第一想法是n^2暴力,但是很不幸,n<=10000,n^2炸了….
怎么办呢….
我们如果把这棵树看成一棵有根树,那么这些点对有两种情况—-一种是两个点在两棵子树中,一种是在一颗子树中…
所以我们可以求出dis[i](所有点到重心的距离—为什么是重心呢…防止退化成n^2),然后在dis数组中On的求出满足要求的点对,然后递归处理它的子树,但是这样会有重复的,所以要减去子树中的ans,也就是说只有路径经过重心的点对才会对答案有贡献
代码如下:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int maxn=10000+5; int hd[maxn],to[maxn*2],nxt[maxn*2],w[maxn*2],cnt,n,barycentre,MIN,ans,dis[maxn],size[maxn],MAX[maxn],num,k; bool vis[maxn]; inline void add(int x,int y,int s){ w[cnt]=s; to[cnt]=y; nxt[cnt]=hd[x]; hd[x]=cnt++; } inline void SIZE(int root,int fa){ size[root]=1,MAX[root]=0; for(int i=hd[root];i!=-1;i=nxt[i]) if(to[i]!=fa&&!vis[to[i]]) SIZE(to[i],root),size[root]+=size[to[i]],MAX[root]=max(MAX[root],size[to[i]]); } inline void findroot(int u,int root,int fa){ MAX[root]=max(MAX[root],size[u]-size[root]); if(MIN>MAX[root]) MIN=MAX[root],barycentre=root; for(int i=hd[root];i!=-1;i=nxt[i]) if(!vis[to[i]]&&to[i]!=fa) findroot(u,to[i],root); } inline void DIS(int root,int fa,int d){ dis[++num]=d; for(int i=hd[root];i!=-1;i=nxt[i]) if(to[i]!=fa&&!vis[to[i]]) DIS(to[i],root,d+w[i]); } inline int calc(int root,int d){ num=0; DIS(root,-1,d); sort(dis+1,dis+num+1); int res=0,x=1,y=num; while(x<y){ while(x<y&&dis[x]+dis[y]>k) y--; res+=y-x; x++; } return res; } inline void dfs(int root){ MIN=n; SIZE(root,-1); findroot(root,root,-1); ans+=calc(barycentre,0); vis[barycentre]=1; for(int i=hd[barycentre];i!=-1;i=nxt[i]) if(!vis[to[i]]) ans-=calc(to[i],w[i]),dfs(to[i]); } signed main(void){ while(scanf("%d%d",&n,&k)&&!(!n&&!k)){ ans=cnt=0,memset(hd,-1,sizeof(hd)); for(int i=1,x,y,s;i<n;i++) scanf("%d%d%d",&x,&y,&s),add(x,y,s),add(y,x,s); memset(vis,0,sizeof(vis)); dfs(1); printf("%d\n",ans); } return 0; }
by >_< neighthorn
相关文章推荐
- poj1741 Tree 点分治
- poj 1741 Tree(树分治)
- 【poj 1741】Tree 【树分治 点分治入门题】
- POJ 1741 Tree 树的点分治
- POJ 1741 Tree(树分治+容斥原理+树的重心)
- poj 1741 Tree 点分治
- 树分治(点分治模板)poj-1741 Tree
- POJ 1741 Tree 树的分治
- POJ 1741 Tree(树的点分治,入门题)
- 数据结构(树,点分治):POJ 1741 Tree
- [POJ 1741]Tree[树分治]
- POJ 1741 Tree (树分治入门)
- 解题报告:POJ1741 Tree 树上点分治(经典好题)
- poj 1741 Tree 树的分治
- poj1741 Tree (求树上任意两点之间权值和小于k的个数)(树分治)
- POJ 1741 Tree (树分治模板题)
- poj 1741 Tree 树的分治
- poj 1741 Tree(点分治)
- POJ 1741 Tree 树+点分治
- poj 1741 Tree 树的分治