【POJ1741】树中点对统计 点分治
来源:互联网 发布:武汉知豆电动车租赁 编辑:程序博客网 时间:2024/05/17 06:45
题目描述
给定一棵N(1<=N<=100000)个结点的带权树,每条边都有一个权值(为正整数,小于等于1001)。定义dis(u,v)为u,v两点间的最短路径长度,路径的长度定义为路径上所有边的权和。再给定一个K(1<=K<=10^9),如果对于不同的两个结点u,v,如果满足dist(u,v)<=K,则称(u,v)为合法点对。求合法点对个数。
题目大意
求树中距离小于k的点对个数
数据范围
对于50%的数据,n<=1000,k<=1000;
对于100%的数据,n<=100000,k<=10^9;
样例输入
5 4
1 2 3
1 3 1
1 4 2
3 5 1
样例输出
8
解题思路
不写了233
代码
#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <ctime>#define Maxn 100005using namespace std;inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}int fa[Maxn],h[Maxn],size[Maxn],dep[Maxn];bool vis[Maxn];int n,k,cnt=0,L,r,Min;struct node{int to,next,v;}e[Maxn*2];void AddEdge(int x,int y,int v){e[++cnt]=(node){y,h[x],v};h[x]=cnt;}void Init(){ n=Getint(),k=Getint(); for(int i=1;i<n;i++){ int x,y,v; x=Getint(),y=Getint(),v=Getint(); fa[y]=x; AddEdge(x,y,v); AddEdge(y,x,v); } memset(vis,0,sizeof(vis));}int dfssize(int u,int pre){ size[u]=1; for(int p=h[u];p;p=e[p].next){ int y=e[p].to; if(vis[y]||y==pre)continue; size[u]+=dfssize(y,u); } return size[u];}void Getroot(int u,int pre,int tot,int &root){ int Max=tot-size[u]; for(int p=h[u];p;p=e[p].next){ int y=e[p].to; if(vis[y]||y==pre)continue; Getroot(y,u,tot,root); Max=max(Max,size[y]); } if(Max<Min){ Min=Max; root=u; }}void Getlen(int u,int pre,int d){ dep[r++]=d; for(int p=h[u];p;p=e[p].next){ int y=e[p].to; if(vis[y]||y==pre)continue; Getlen(y,u,d+e[p].v); }}int Calc(int L,int r){ sort(dep+L,dep+r); int ret=0,Pos=r-1; for(int i=L;i<r;i++){ if(dep[i]>k)break; while(Pos>=L&&dep[i]+dep[Pos]>k)Pos--; ret+=Pos-L+1; if(Pos>i)ret--; } return ret/2;}int Solve(int u){ int tot=dfssize(u,0),ret=0,root; Min=0x7fffffff; Getroot(u,0,tot,root); vis[root]=true; for(int p=h[root];p;p=e[p].next){ int y=e[p].to; if(vis[y])continue; ret+=Solve(y); } L=r=0; for(int p=h[root];p;p=e[p].next){ int y=e[p].to; if(vis[y])continue; Getlen(y,root,e[p].v); ret-=Calc(L,r); L=r; } ret+=Calc(0,r); for(int i=0;i<r;i++) if(dep[i]<=k)ret++; else break; vis[root]=false; return ret;}int main(){ Init(); cout<<Solve(1)<<"\n";}
0 0
- 【POJ1741】树中点对统计 点分治
- [POJ1741][JZOJ1166] 树中点对距离(点分治模板)
- BSOJ2764:树中点对统计 点分治
- 树中点对距离(点分治)
- poj1741 树的点分治
- POJ1741树的分治之点分治
- 点分治模板 (树中点对距离)
- 【POJ1741】Tree-树的点分治
- 点分治 poj1741
- [Poj1741]Tree (点分治)
- poj1741 树上点分治
- poj1741(点分治)
- poj1741 Tree 点分治
- [POJ1741]Tree |点分治
- POJ1741 点分治
- poj1741 Tree 点分治
- 【poj1741】Tree 点分治
- poj1741 tree 点分治
- 单应性(homography)变换的推导
- SSO 之 (单点登录)实施中遇到的几个问题
- bootstrap-图文对象列表
- eclipse最有用快捷键整理
- bzoj 2226: [Spoj 5971] LCMSum线性筛欧拉函数
- 【POJ1741】树中点对统计 点分治
- Lind.DDD.LindMQ的一些想法
- 怎么设置win7远程桌面
- swift字典
- 生产系统搭建spark,基础环境注意事项
- 内连接,外链接,交叉链接的区别
- MB消息集开发示例
- Learning Theory---误差理论(Error Theory)
- 小程序爬坑