http://poj.org/problem?id=1987

题意:给一棵树,求树上有多少对节点满足距离<=K

思路:点分治,我们考虑把每个距离都存起来,然后排序,一遍扫描计算一下,注意还要减掉自己加自己的方案。而且,我们还要去掉走到同一个子树的方案。复杂度:O(nlog^2n)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
int tot,go[],first[],next[];
ll st[],val[];
int sum,son[],root,n,F[],c[];
int pd[],sz,vis[];
ll dis[];
int cnt,K,ans;
int read(){
int t=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (''<=ch&&ch<=''){t=t*+ch-'';ch=getchar();}
return t*f;
}
void insert(int x,int y,int z){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
val[tot]=z;
}
void add(int x,int y,int z){
insert(x,y,z);insert(y,x,z);
}
void findroot(int x,int fa){
son[x]=;F[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa||vis[pur]) continue;
findroot(pur,x);
son[x]+=son[pur];
F[x]=std::max(F[x],son[pur]);
}
F[x]=std::max(F[x],sum-son[x]);
if (F[x]<F[root]) root=x;
}
void bfs(int x){
int h=,t=;c[]=x;pd[x]=sz;dis[x]=;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (vis[pur]||pd[pur]==sz) continue;
pd[pur]=sz;
dis[pur]=dis[now]+val[i];
c[++t]=pur;
st[++cnt]=dis[pur];
}
}
std::sort(st+,st++cnt);
int j=cnt,res=,Cnt=;
for (int i=;i<=t;i++){
while (j>&&st[i]+st[j]>K) j--;
if (st[i]+st[j]<=K) res+=j;
if (st[i]+st[i]<=K) Cnt++;
}
res-=Cnt;
ans+=res/;
}
int del(int x,int Dis){
dis[x]=Dis;sz++;
int h=,t=;cnt=;st[cnt]=Dis;
pd[x]=sz;c[]=x;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (pd[pur]==sz||vis[pur]) continue;
dis[pur]=dis[now]+val[i];
st[++cnt]=dis[pur];
pd[pur]=sz;
c[++t]=pur;
}
}
int j=cnt,res=,Cnt=;
std::sort(st+,st++cnt);
for (int i=;i<=t;i++){
while (j>&&st[i]+st[j]>K) j--;
if (st[i]+st[j]<=K) res+=j;
if (st[i]+st[i]<=K) Cnt++;
}
res-=Cnt;
return res/;
}
void solve(int x){
vis[x]=;++sz;
cnt=;st[cnt]=;
bfs(x);
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
ans-=del(pur,val[i]);
}
int Cnt=sum;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
if (son[pur]>son[x]) sum=Cnt-son[x];
else sum=son[pur];
root=;
findroot(pur,x);
solve(root);
}
}
int main(){
int m;
char s[];
scanf("%d%d\n",&n,&m);
for (int i=;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
scanf("%s",s+);
}
scanf("%d\n",&K);
F[]=0x7fffffff;
root=;sum=n;
findroot(,);
solve(root);
printf("%d\n",ans);
}

POJ 1987 Distance Statistics的更多相关文章

  1. POJ 1987 Distance Statistics 树分治

    Distance Statistics     Description Frustrated at the number of distance queries required to find a ...

  2. POJ 1987 Distance Statistics(树的点分治)

      转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 上场CF的C题是一个树的分治... 今天刚好又 ...

  3. POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 【USACO】距离咨询(最近公共祖先)

    POJ 1986 Distance Queries / UESTC 256 Distance Queries / CJOJ 1129 [USACO]距离咨询(最近公共祖先) Description F ...

  4. BZOJ_3365_[Usaco2004 Feb]Distance Statistics 路程统计&&POJ_1741_Tree_点分治

    BZOJ_3365_[Usaco2004 Feb]Distance Statistics 路程统计&&POJ_1741_Tree_点分治 Description     在得知了自己农 ...

  5. POJ.1986 Distance Queries ( LCA 倍增 )

    POJ.1986 Distance Queries ( LCA 倍增 ) 题意分析 给出一个N个点,M条边的信息(u,v,w),表示树上u-v有一条边,边权为w,接下来有k个询问,每个询问为(a,b) ...

  6. POJ 1986 Distance Queries LCA两点距离树

    标题来源:POJ 1986 Distance Queries 意甲冠军:给你一棵树 q第二次查询 每次你问两个点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + d ...

  7. POJ 1987 BZOJ 3365 Distance Statistics 树的分治(点分治)

    题目大意:(同poj1741,刷一赠一系列) CODE: #include <cstdio> #include <cstring> #include <iostream& ...

  8. 【poj1987】 Distance Statistics

    http://poj.org/problem?id=1987 (题目链接) 题意 给出一棵树,求树上距离不超过K的点对个数. Solution 点分治,同poj1741. 代码 // poj1987 ...

  9. POJ 1986 Distance Queries(Tarjan离线法求LCA)

    Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 12846   Accepted: 4552 ...

随机推荐

  1. windows 编程—— 常用函数 与 操作

    目录: MessageBox() 和 PlaySound() 获得窗口 或屏幕大小 获得字体大小 输出文字 屏蔽和显示控制台窗口 1. MessageBox() 和 PlaySound() Messa ...

  2. js的深拷贝和浅拷贝

    一.数组的深浅拷贝 在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致 ...

  3. Ubuntu 13.04编译boost1.54

    因为要用基于GCC4.8.1的boost最新版本的库,默认apt-get install 安装的是boost1.53, 并且基于GCC4.7.3,不是我想要的.所以决定下载源代码自己编译. 下载(后面 ...

  4. QT 仓库管理系统 开放源代码

    IT 要走多久,要怎么走. IT 要走多久,要怎么走.这些问题,在我已经快毕业了一个年头的如今,又又一次浮如今我的脑海里.一边是工作的了了模块,一边是能够自己无聊打发的时间.这不是我当初要的路,如今的 ...

  5. 【错误总结之(一)】error LNK2038: 检測到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”

    1>cvblob.lib(cvblob.obj) : error LNK2038: 检測到"_ITERATOR_DEBUG_LEVEL"的不匹配项: 值"0&quo ...

  6. where子句的具体含义

    今天同学让我帮他调代码,下面是出错的那句: txtSQL= "select * from student_Info where UserID='" & cboUserID. ...

  7. 混血儿爹妈要混的远,数据库与WEB分离,得混的近

    最近搞了个漫画网站,放在香港VPS,由于内存不够,把数据库移到了阿里云,混的远了点,没缓存的时候网站打开速度慢了1秒左右.笨狗漫画:http://www.bengou8.com 底部有sql时间cop ...

  8. [转] Python 模块学习:os模块

    一.os模块概述 Python os模块包含普遍的操作系统功能.如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的.(一语中的) 二.常用方法 1.os.name 输出字符串指示正在使用的平台 ...

  9. NYOJ-569最大公约数之和

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=569 此题目可以用筛选法的思想来做,但是用到一个欧拉函数 gcd(1,12)=1,gcd( ...

  10. eclipse中svn版本不兼容问题

    eclipse中导入本地svn管理的Android项目 使用svn时弹出以下提示: org.apache.subversion.javahl.ClientException: Unsupported ...