[codeforces161D]Distance in Tree(点分治)

题意:求树上距离为k的点对个数;

解题关键:练习一下点分治不用容斥 而直接做的做法。注意先查询,后更新。

不过这个方法有个缺陷,每次以一个新节点为根,必须memset mp数组,或许使用map会好些,更新序号一类用ca这种形式更好些。

试了一下,map更慢,应该是带log的原因。

  1 #pragma comment(linker,"/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 #include<iostream>
  7 #include<cmath>
  8 #include<map>
  9 #define maxn 100040
 10 #define maxm 1000500
 11 using namespace std;
 12 typedef long long ll;
 13 const ll mod=1000003;
 14 const ll inf=1ll<<60;
 15 ll n,k,ans,size,s[maxn],f[maxn],path[maxn],cr;
 16 ll head[maxn],cnt,root;
 17 bool vis[maxn];
 18 struct edge{
 19     ll to,nxt;
 20 }e[maxn<<1];
 21 map<int,int>mp;
 22 void add_edge(ll u,ll v){
 23     e[cnt].to=v;
 24     e[cnt].nxt=head[u];
 25     head[u]=cnt++;
 26 }
 27
 28 inline ll read(){
 29     char k=0;char ls;ls=getchar();for(;ls<‘0‘||ls>‘9‘;k=ls,ls=getchar());
 30     ll x=0;for(;ls>=‘0‘&&ls<=‘9‘;ls=getchar())x=(x<<3)+(x<<1)+ls-‘0‘;
 31     if(k==‘-‘)x=0-x;return x;
 32 }
 33
 34 void get_root(ll u,ll fa){//get_root会用到size
 35     s[u]=1;f[u]=0;//f是dp数组
 36     for(ll i=head[u];i!=-1;i=e[i].nxt){
 37         ll v=e[i].to;
 38         if(v==fa||vis[v]) continue;
 39         get_root(v,u);
 40         s[u]+=s[v];
 41         f[u]=max(f[u],s[v]);
 42     }
 43     f[u]=max(f[u],size-s[u]);
 44     root=f[root]>f[u]?u:root;
 45 }
 46
 47 void get_path_size(ll u,ll fa,ll dis){
 48     if(dis+1<=k){
 49         path[cr]=dis+1;
 50         cr++;
 51     }
 52     s[u]=1;
 53     for(ll i=head[u];i!=-1;i=e[i].nxt){
 54         ll v=e[i].to;
 55         if(v==fa||vis[v]) continue;
 56         get_path_size(v,u,dis+1);
 57         s[u]+=s[v];
 58     }
 59 }
 60
 61 void work(ll u,ll fa){
 62     vis[u]=true;
 63     mp.clear();
 64     mp[0]=1;
 65     for(ll i=head[u];i!=-1;i=e[i].nxt){
 66         ll v=e[i].to;
 67         if(v==fa||vis[v]) continue;
 68         cr=0;
 69         get_path_size(v,u,0);
 70         for(ll j=0;j<cr;j++){
 71             ans+=mp[k-path[j]];
 72         }
 73         for(int j=0;j<cr;j++){
 74             mp[path[j]]++;
 75         }
 76     }
 77     for(ll i=head[u];i!=-1;i=e[i].nxt){
 78         ll v=e[i].to;
 79         if(vis[v]||v==fa) continue;
 80         size=s[v],root=0;
 81         get_root(v,u);
 82         work(root,u);
 83     }
 84 }
 85
 86 void init(){
 87     memset(vis,0,sizeof vis);
 88     memset(head,-1,sizeof head);
 89     ans=cnt=0;
 90 }
 91
 92 int main(){
 93     ll a,b;
 94     f[0]=inf;
 95     while(scanf("%I64d%I64d",&n,&k)!=EOF){
 96         init();
 97         for(int i=0;i<n-1;i++){
 98             a=read(),b=read();
 99             add_edge(a,b);
100             add_edge(b,a);
101         }
102         size=n,root=0;
103         get_root(1,-1);
104         work(root,-1);
105         printf("%d\n",ans);
106     }
107     return 0;
108 }
时间: 2024-08-03 11:29:12

[codeforces161D]Distance in Tree(点分治)的相关文章

codeforces161D - Distance in Tree 树形dp

题意:给你一棵树,问你树中距离为k的有多少种情况. 解题思路:树形dp  维护每个节点(1-K)深度的情况, 解题代码: 1 // File Name: 161d.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月03日 星期日 19时20分10秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #incl

Codechef Prime Distance On Tree(点分治+FFT)

题外话 最近做题发现自己非常SB,总是查一个SB错误查N久,简直绝望啊...弱逼为何而战 这次是忘记加long long查了N久..蛋碎无比 不过好歹是又做出一道cc hard的题了呢,感人肺腑 Description 题意很简单: 一棵树,问多少个二元组(u,v),满足u 到 v的路径长度为素数的概率为多少.所有边长度为1 Solution 自从重温了下 楼教的男人八题后,这种关于路径长度的题一看就是个点分治嘛 显然我们可以点分治统计路径长度,但是显然无法用two pointers或者数据结构

CF161D Distance in Tree |点分治

题目大意 输入点数为N一棵树 求树上长度恰好为K的路径个数 输入格式 第一行两个数字N,K,如题意 接下来的N?1行中,每行两个整数u,v表示一条树边(u,v) 输出格式 一个整数ans,如题意 直接套模板,没啥好说的 #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<iostream> #include<map> using

codeforces 161D - Distance in Tree(树形dp)

题目大意: 求出树上距离为k的点对有多少个. 思路分析: dp[i][j] 表示 i 的子树中和 i 的距离为 j 的点数有多少个.注意dp[i] [0] 永远是1的. 然后在处理完一颗子树后,就把自身的dp 更新. 更新之前更新答案. 如果这颗子树到 i 有 x 个距离为j的.那么答案就要加上 dp[i] [ k-j-1] * x; #include <iostream> #include <cstdio> #include <cstring> #include &l

[LeetCode] Convert Sorted List to Binary Search Tree(分治)

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST. 方法:为了使BST高度平衡,要找链表中的中值作为当前根节点. /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) :

CodeForces161D: Distance in Tree

A tree is a connected graph that doesn't contain any cycles. The distance between two vertices of a tree is the length (in edges) of the shortest path between these vertices. You are given a tree with n vertices and a positive number k. Find the numb

codechef Prime Distance On Tree(树分治+FFT)

题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治,对于每个根出发记录边的长度出现几次,然后每次求卷积,用素数表查一下即可添加答案. 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include

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

CodeChef PRIMEDST Prime Distance On Tree

Description All submissions for this problem are available. Problem description. You are given a tree. If we select 2 distinct nodes uniformly at random, what's the probability that the distance between these 2 nodes is a prime number? Input The firs