【poj1987】Distance Statistics
2016-07-19 15:32
323 查看
link to problem
//听说1741也是一样的题目啊(⊙o⊙)
【题目大意】
给出一棵树,求树上有多少个点对 ( i , j ) 满足dis( i , j )<=k (1 <= k <= 1,000,000,000)。
【题解】点分治入门题
本题关键在于k太大了,无法水过QAQ
于是我们开始思考,在一棵根为rt(既然是点分治根节点显然就是树的重心了)的树内符合条件的点对( i , j ),可以分为以下两种情况:
( 1 ) 点 i,j 都在rt的某一棵子树中;
( 2 ) 点 i,j 分别在rt的两棵不同子树中;
显然对于情况(1)我们可以把它分解为情况(2)的方法来做。
于是对于一棵树,求出树内所有节点到根节点的距离,算出满足dis[i]+dis[j]<=k的点对(i,j)的数量。不过在这些点对中可能存在在同一棵子树里的情况,于是将它们扣除就得到为我们所要求的答案啦。
【呆马(⊙v⊙)】
//听说1741也是一样的题目啊(⊙o⊙)
【题目大意】
给出一棵树,求树上有多少个点对 ( i , j ) 满足dis( i , j )<=k (1 <= k <= 1,000,000,000)。
【题解】点分治入门题
本题关键在于k太大了,无法水过QAQ
于是我们开始思考,在一棵根为rt(既然是点分治根节点显然就是树的重心了)的树内符合条件的点对( i , j ),可以分为以下两种情况:
( 1 ) 点 i,j 都在rt的某一棵子树中;
( 2 ) 点 i,j 分别在rt的两棵不同子树中;
显然对于情况(1)我们可以把它分解为情况(2)的方法来做。
于是对于一棵树,求出树内所有节点到根节点的距离,算出满足dis[i]+dis[j]<=k的点对(i,j)的数量。不过在这些点对中可能存在在同一棵子树里的情况,于是将它们扣除就得到为我们所要求的答案啦。
【呆马(⊙v⊙)】
#include <cstdio> #include <algorithm> #define maxn 100000 struct edge{ int to,s,nxt;}e[maxn]; int n,m,cnt,k,mx,rt,ans,tot, fi[maxn],dis[maxn],d[maxn],size[maxn],f[maxn]; bool bo[maxn]; void add(int u,int v,int w) { e[++cnt].to=v;e[cnt].s=w; e[cnt].nxt=fi[u];fi[u]=cnt; } void findrt(int x,int fa) { int mxx=0;size[x]=1; for (int i=fi[x];i;i=e[i].nxt) if (e[i].to!=fa && !bo[e[i].to]) { findrt(e[i].to,x); size[x]+=size[e[i].to]; mxx=std::max(mxx,size[e[i].to]); } mxx=std::max(mxx,tot-mxx); if (mxx<mx) rt=x,mx=mxx; } void dfs(int x,int fa) { d[++d[0]]=dis[x]; for (int i=fi[x];i;i=e[i].nxt) if (fa!=e[i].to && !bo[e[i].to]) { dis[e[i].to]=dis[x]+e[i].s; dfs(e[i].to,x); } } int cal(int x) { d[0]=0;dfs(x,0); std::sort(d+1,d+d[0]+1); int ans=0; for (int l=1,r=d[0];l<=r;) if (d[l]+d[r]<=k) ans+=r-l,++l; else --r; return ans; } void dp(int x) { bo[x]=true; dis[x]=0;ans+=cal(x); for (int i=fi[x];i;i=e[i].nxt) if (!bo[e[i].to]) { dis[x]=e[i].s; ans-=cal(e[i].to); rt=0;mx=tot=size[e[i].to]; findrt(e[i].to,0); dp(rt); } } int main() { scanf("%d%d\n",&n,&k); for (int i=1;i<n;++i) { int u,v,w;char ch; scanf("%d %d %d\n",&u,&v,&w); add(u,v,w);add(v,u,w); } mx=tot=n;rt=0;findrt(1,0); dp(rt);printf("%d\n",ans); return 0; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2159 Ancient Cipher
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- [数论]poj2635__The Embarrassed Cryptographer
- [二分图匹配]poj2446__Chessboard
- POJ1050 最大子矩阵和
- 用单调栈解决最大连续矩形面积问题