POJ1751 Tree 树分治

分析:每次找重心可以发现最多n层,每层复杂度是O(nlogn) 总体时间复杂度是O(nlog^2n)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <stdlib.h>
using namespace std;
typedef long long LL;
const int N=1e4+5;
int head[N],tot,n,k,ret,cnt,sz[N],rt,p,dis[N],mx[N];
bool vis[N];
struct Edge{
  int v,w,next;
}edge[N<<1];
void add(int u,int v,int w){
  edge[tot].v=v;
  edge[tot].w=w;
  edge[tot].next=head[u];
  head[u]=tot++;
}
void getsz(int u,int f){
  sz[u]=1;mx[u]=0;
  for(int i=head[u];~i;i=edge[i].next){
    int v=edge[i].v;if(v==f||vis[v])continue;
    getsz(v,u);sz[u]+=sz[v];
    if(sz[v]>mx[u])mx[u]=sz[v];
  }
}
void getroot(int tp,int u,int f){
  mx[u]=max(mx[u],sz[tp]-sz[u]);
  if(mx[u]<cnt)cnt=mx[u],rt=u;
  for(int i=head[u];~i;i=edge[i].next){
    int v=edge[i].v;if(v==f||vis[v])continue;
    getroot(tp,v,u);
  }
}
void getdis(int u,int f,int d){
  dis[++p]=d;
  for(int i=head[u];~i;i=edge[i].next){
    int v=edge[i].v;if(v==f||vis[v])continue;
    getdis(v,u,d+edge[i].w);
  }
}
int cal(int u,int d){
  int ans=0;
  p=0;
  getdis(u,-1,d);
  sort(dis+1,dis+1+p);
  for(int i=1,j=p;i<j;++i){
    while(dis[i]+dis[j]>k&&i<j)--j;
    ans+=j-i;
  }
  return ans;
}
void dfs(int u){
  cnt=n;getsz(u,-1);getroot(u,u,-1);
  ret+=cal(rt,0);vis[rt]=true;
  for(int i=head[rt];~i;i=edge[i].next){
    int v=edge[i].v;if(vis[v])continue;
    ret-=cal(v,edge[i].w);
    dfs(v);
  } 

}
int main(){
  while(~scanf("%d%d",&n,&k),n&&k){
     for(int i=1;i<=n;++i)head[i]=-1,vis[i]=false;
     ret=tot=0;
     for(int i=1;i<n;++i){
      int u,v,w;scanf("%d%d%d",&u,&v,&w);
      add(u,v,w);add(v,u,w);
     }
     dfs(1);
     printf("%d\n",ret);
  }
  return 0;
}

时间: 2024-11-10 20:38:08

POJ1751 Tree 树分治的相关文章

poj 1744 tree 树分治

Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of ve

【BZOJ-1468】Tree 树分治

1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k Output 一行,有多少对点之间的距离小于等于k Sample Input 7 1 6 13 6

HDU 4812 D Tree 树分治+逆元处理

D Tree Problem Description There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each bran

【POJ1741】Tree 树分治 模板咯?

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44302921"); } 题意: 给你一棵无根树,求有多少点对之间距离<=K. 题解: 树分治. 然后对于一个重心X,我们把它的所有子树中的所有点存到结构体数组中. 结构体中存距离和子树编号. 第一遍sort,我们双指针扫哪些点

HDU 4812 D Tree 树分治+逆元+hash新姿势

题意: 给定n个点的树 K 下面n个数是点权 下面n-1行给出树边. 问: 是否存在一条路径使得路径上点权积 % mod  = K 若存在则输出路径的两端. 若存在多条路径则输出字典序最小的一条. 思路: 按树重心分治. 分成路径是否经过树重心. 然后用力码.. has[x] = u; 表示乘积为x 对应的点是u 但这样has就不能用计数器来优化清空. 所以用2个数组: has[x] = cnt; has_id[x] = u; 这样has里存的是乘积为x是否存在.has_id[x] 来记录点.

POJ 1741 Tree 树分治(点分治)

题意:给你一颗带边权树,问你其中 dis(v,u) <= k 的对数 解题思路: 首先推荐大家看 09年国家集训队漆子超 的论文 看到这题  我们可以有三种思路 第一种是枚举起点,遍历整颗树找对数    时间复杂度 为  O(n^2),空间复杂度为 O(n) 第二种是树形dp的思想     每个节点用 长度为 K 数组维护 ,递归求解  时间复杂度为 O(n ^k)空间复杂度 为 O(n) 第三种就是我们要用到的点分治的思想. 这种思想的具体思路是  先找到一个  根  对这个根进行 深搜, 找

ZOJ 3863 Paths on the Tree 树分治

题目链接:点击打开链接 题意: 给定n个点的树. 常量k 问:对于一对路径,如果公共点<=k则为合法. 问有多少个合法的路径. {1-3, 2-4} 和 {2-4,1-3} 视为2个不同的路径对. 1-3, 3-1视为相同路径. 思路: 首先来得到一个O(n^3)的算法: 把问题转成=> 总方案数 - 公共点>k个的路径对数 显然公共点是连续的,所以公共点会组成一条路径,我们设为 x-y,则枚举x和y,就能得到公共的部分(当然要保证x-y的公共点数>k) 那么现在的问题是 以公共路

POJ 1741 Tree(树分治)

去网上搜题解大多数都是说论文,搜了论文看了看,写的确实挺好,直接复制过来. 不过代码中有些细节还是要注意的,参考这篇http://blog.sina.com.cn/s/blog_6d5aa19a0100o73m.html一段 设X为满足i<j且Depth[i]+Depth[j]<=K的数对(i,j)的个数设Y为满足i<j,Depth[i]+Depth[j]<=K且Belong[i]=Belong[j]数对(i,j)的个数那么我们要统计的量便等于X-Y 求X.Y的过程均可以转化为以下

树分治基础模板以及树的重心(poj1741 tree)

好久没有更新博文了,这里更新一发~~ Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v