[codeforces161D]Distance in Tree(点分治/树形dp)
题意:求树上距离为k的点对个数;
解题关键:练习一下点分治不用容斥 而直接做的做法。注意先查询,后更新。
不过这个方法有个缺陷,每次以一个新节点为根,必须memset mp数组,或许使用map会好些,更新序号一类用ca这种形式更好些。
试了一下,map更慢,应该是带log的原因。
点分治解法:
#pragma comment(linker,"/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<map>
#define maxn 100040
#define maxm 1000500
using namespace std;
typedef long long ll;
const ll mod=;
const ll inf=1ll<<;
ll n,k,ans,size,s[maxn],f[maxn],path[maxn],cr;
ll head[maxn],cnt,root;
bool vis[maxn];
struct edge{
ll to,nxt;
}e[maxn<<];
map<int,int>mp;
void add_edge(ll u,ll v){
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
} inline ll read(){
char k=;char ls;ls=getchar();for(;ls<''||ls>'';k=ls,ls=getchar());
ll x=;for(;ls>=''&&ls<='';ls=getchar())x=(x<<)+(x<<)+ls-'';
if(k=='-')x=-x;return x;
} void get_root(ll u,ll fa){//get_root会用到size
s[u]=;f[u]=;//f是dp数组
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
get_root(v,u);
s[u]+=s[v];
f[u]=max(f[u],s[v]);
}
f[u]=max(f[u],size-s[u]);
root=f[root]>f[u]?u:root;
} void get_path_size(ll u,ll fa,ll dis){
if(dis+<=k){
path[cr]=dis+;
cr++;
}
s[u]=;
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
get_path_size(v,u,dis+);
s[u]+=s[v];
}
} void work(ll u,ll fa){
vis[u]=true;
mp.clear();
mp[]=;
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(v==fa||vis[v]) continue;
cr=;
get_path_size(v,u,);
for(ll j=;j<cr;j++){
ans+=mp[k-path[j]];
}
for(int j=;j<cr;j++){
mp[path[j]]++;
}
}
for(ll i=head[u];i!=-;i=e[i].nxt){
ll v=e[i].to;
if(vis[v]||v==fa) continue;
size=s[v],root=;
get_root(v,u);
work(root,u);
}
} void init(){
memset(vis,,sizeof vis);
memset(head,-,sizeof head);
ans=cnt=;
} int main(){
ll a,b;
f[]=inf;
while(scanf("%I64d%I64d",&n,&k)!=EOF){
init();
for(int i=;i<n-;i++){
a=read(),b=read();
add_edge(a,b);
add_edge(b,a);
}
size=n,root=;
get_root(,-);
work(root,-);
printf("%d\n",ans);
}
return ;
}
树形dp解法:
复杂度:$O(nk)$
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 100006
int head[maxn],cnt,dp[maxn][];
struct edge{
int to,w,nxt;
}e[maxn<<];
ll ans;
int n,k,a,b;
void add_edge(int u,int v){
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
} void dfs(int u,int fa){
dp[u][]=;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
for(int j=;j<=k;j++){
dp[u][j]+=dp[v][j-];
}
}
ans+=dp[u][k];
int tmp=;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
for(int j=;j<k;j++){
tmp+=1ll*dp[v][j-]*(dp[u][k-j]-dp[v][k-j-]);
}
}
ans+=tmp/;
} void init(){
memset(head,-,sizeof head);
cnt=;
ans=;
} int main(){
init();
cin>>n>>k;
for(int i=;i<n-;i++){
cin>>a>>b;
add_edge(a,b);
add_edge(b,a);
}
dfs(,-);
cout<<ans<<"\n";
return ;
}
[codeforces161D]Distance in Tree(点分治/树形dp)的更多相关文章
- 『You Are Given a Tree 整体分治 树形dp』
You Are Given a Tree Description A tree is an undirected graph with exactly one simple path between ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- Codeforces 791D Bear and Tree Jump(树形DP)
题目链接 Bear and Tree Jumps 考虑树形DP.$c(i, j)$表示$i$最少加上多少后能被$j$整除. 在这里我们要算出所有$c(i, k)$的和. 其中$i$代表每个点对的距离, ...
- [HDU 5293]Tree chain problem(树形dp+树链剖分)
[HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...
- E. Alternating Tree 树点分治|树形DP
题意:给你一颗树,然后这颗树有n*n条路径,a->b和b->a算是一条,然后路径的权值是 vi*(-1)^(i+1) 注意是点有权值. 从上头往下考虑是点分治,从下向上考虑就是树形DP, ...
- Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
原文链接https://www.cnblogs.com/zhouzhendong/p/CF980F.html 题目传送门 - CF980F 题意 给定一个 $n$ 个节点 $m$ 条长为 $1$ 的边 ...
- hdu5293 Tree chain problem 树形dp+线段树
题目:pid=5293">http://acm.hdu.edu.cn/showproblem.php?pid=5293 在一棵树中,给出若干条链和链的权值.求选取不相交的链使得权值和最 ...
- [BZOJ2152]聪聪可可 点分治/树形dp
2152: 聪聪可可 Time Limit: 3 Sec Memory Limit: 259 MB Submit: 3602 Solved: 1858 [Submit][Status][Discu ...
- CodeChef - PRIMEDST Prime Distance On Tree 树分治 + FFT
Prime Distance On Tree Problem description. You are given a tree. If we select 2 distinct nodes unif ...
随机推荐
- 基于zookeeper或redis实现分布式锁
前言 在分布式系统中,分布式锁是为了解决多实例之间的同步问题.例如master选举,能够获取分布式锁的就是master,获取失败的就是slave.又或者能够获取锁的实例能够完成特定的操作. 目前比较常 ...
- VC项目文件说明
.dsp 项目参数配置文件,这个文件太重要,重点保护对象.. .dsw 工作区文件,重要性一般,因为它信息不我,容易恢复. 以下文件在项目中是可丢弃的,有些文件删除后,VC会自动生成的. ...
- 九度OJ 1160:放苹果 (DFS)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:998 解决:680 题目描述: 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和 ...
- cmake policy
1 cmake policy是什么? cmake policy可以理解为cmake的语法标准,也就是说,它规定了cmake在解析CMakeLists.txt文件时的行为. 2 cmake policy ...
- Gemini.Workflow 双子工作流入门教程一:定义流程:流程图属性
简介: Gemini.Workflow 双子工作流,是一套功能强大,使用简单的工作流,简称双子流,目前配套集成在Aries框架中. 下面介绍本篇教程:流程定义:流程图属性. 步骤一:在流程管理的流程定 ...
- spring cloud初识
spring cloud是spring中的一个快速开发框架.本实例采用spring+maven来配置一个简单的spring开发实例. 1.首先安装java和maven环境. ①.安装java,不做过多 ...
- java2 -宏观了解
java2 -宏观了解 2016-01-24 16:17 308人阅读 评论(38) 收藏 举报 分类: JAVA(2) 版权声明:本文为博主原创文章,未经博主允许不得转载. Java2平台包括: ...
- Appium——api常用函数
appium常用函数介绍: 获取页面信息: 1. def get_current_activity(cls, driver): ''' 获取当前页面的activity :param drive ...
- python类初探
class human: is_alive=True is_man=True def __init__(self,age): print('this is __init__() method, whi ...
- Ajax处理后台返回的Json数据
// 处理后台传来的Json字符串装换成Json对象 var dataJson = JSON.parse(data); // 此时可以从Json对象中取值 if(dataJson.result == ...