POJ 1741 Tree 点分治
来源:互联网 发布:杭州月嫂哪家好 知乎 编辑:程序博客网 时间:2024/05/21 08:47
时空隧道
题目大意:
给出一棵树,求出这棵树上满足要求的点对有多少个—-要求是两点之间距离小于等于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
1 0
- 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 1741Tree(点分治)
- 点分治 POJ 1741 Tree
- POJ 1741 Tree 点分治
- poj 1741 Tree (点分治)
- POJ 1741 Tree 点分治
- POJ 1741 Tree【Tree,点分治】
- POJ 1741 Tree【Tree,点分治】
- poj 1741 Tree (点的分治)
- POJ 1741 Tree 树的点分治
- POJ 1741 Tree(树上的点分治)
- android之ConnectivityManager简介,网络连接状态
- Ubuntu:安装常用软件找不到安装包时的解决办法
- Java集合Set、List、Map的遍历方法
- android 飘心动画(直播点赞)效果(二)---贝塞尔曲线的实现
- MVP模式
- POJ 1741 Tree 点分治
- visual studio 调试
- Class定义和用法
- 源代码管理工具SVN和Git小结
- leetcode:Trie:Word Search II(212)
- Verilog testbench的写法之输入输出文件
- 异步刷新UI
- box-shadow是向盒子添加阴影
- 就是为了上传图片