bzoj 3522 tree-dp 暴力
首先我们知道,这个题可以N^2的做,我们先确定一个根,然后讨论下情况,合法的三个点只可能有三种情况,第一种是三个点有相同的lca,这种情况我们可以用tree-dp来解决,用dis[i][j]表示i为根的子树中距离i为j的点的数量,然后我们枚举儿子,处理出dis_[i][j]表示i子树中选两个点距离i为j的点对儿数量,且在不同子树中(到i路径无重合)。那么枚举儿子的时候可以处理出这种情况的答案。
还有一种情况为在i的子树中选2个不同子树中的点,也是就dis_[i][j],然后第三个点不在i的子树中,那么我们枚举每一个点,bfs出距离这个点距离为j的且不在i的子树中的点的数量为fuck_dis[i][j],那么ans+=dis_[i][j]*fuck_dis[i][j]。因为每个节点只会有一个父亲,所以最多只能向上引一条不重叠的链,保证了算法的正确性。
反思:这道题不算特别难,但是写了挺长时间,开始的时候之想到了第一中情况,第二种情况只考虑了对于两个点距离i为j,i的一个祖先距离i为j,然后这个祖先可以成为答案,就用i的dep来判一下就好了。但是还有其他的可能,比如在某个地方拐一下,这个点到i的距离为j,所以我又写了每个点到除去子树中的点的距离最远的点,大于了j就可以更新答案,但是没有考虑到这个点有多种选法,所以最后写的距离i为j的点且不在i的子树中的数量,这个开始我想的是tree-dp,想了想觉得很不好写,总之tree-dp也是n^2,所以就写了每个点的bfs。
备注:还有另外一种方法,其实我们第一种方法的本质就是讨论,我们可以发现所有满足条件的点对儿都可以通过选取不同的根来看成三个点有一个lca,那么我们可以枚举所有的点,然后bfs,每做一层我们都统计一下答案,方法和上一种方法的第一种情况类似,这种方法可以节省空间,但是觉得不是特别好写。
这道题没有链的数据,我用dis[i][j]存的每个点的信息,但是n^2的内存会超,所以就估了一下不会超过2500左右,然后就把数组开小了些,其实应该用vector来存或者最开始选根的时候选重心来保证这个,但是懒得写了= =。
/**************************************************************
Problem: 3522
User: BLADEVIL
Language: C++
Result: Accepted
Time:2620 ms
Memory:118816 kb
****************************************************************/ //By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 5010
#define inf (~0U>>1) using namespace std; int n,l;
long long ans;
int pre[maxn<<],other[maxn<<],last[maxn];
int que[maxn],dep[maxn],dis[maxn][],dis_[maxn][],que_[maxn],dep_[maxn],father[maxn];
int jump[maxn][],fuck_dis[maxn][]; void connect(int x,int y) {
pre[++l]=last[x];;
other[l]=y;
last[x]=l;
} int main() {
//freopen("hot.in","r",stdin); freopen("hot.out","w",stdout);
scanf("%d",&n);
for (int i=;i<n;i++) {
int x,y; scanf("%d%d",&x,&y);
connect(x,y); connect(y,x);
}
int h=,t=; que[]=; dep[]=;
while (h<t) {
int cur=que[++h];
for (int p=last[cur];p;p=pre[p]) {
if (dep[other[p]]) continue;
que[++t]=other[p]; dep[other[p]]=dep[cur]+;
father[other[p]]=cur;
}
}
//for (int i=1;i<=n;i++) printf("%d ",standard[i]);
//for (int i=1;i<=n;i++) printf("%d ",que[i]);printf("\n");
for (int i=n;i;i--) {
int cur=que[i],sum=;
for (int p=last[cur];p;p=pre[p]) {
if (dep[other[p]]<dep[cur]) continue;
for (int j=;j<=dis[other[p]][];j++) ans+=dis_[cur][j+]*dis[other[p]][j];
ans+=dis_[cur][];
for (int j=;j<=dis[other[p]][];j++) dis_[cur][j+]+=dis[cur][j+]*dis[other[p]][j];
dis_[cur][]+=sum;
dis[cur][]=max(dis[cur][],dis[other[p]][]+);
for (int j=;j<=dis[other[p]][];j++) dis[cur][j+]+=dis[other[p]][j];
dis[cur][]++; sum++;
}
//printf("|%d %d\n",cur,dis[cur][1]);
//printf("||%d %d\n",cur,ans);
}
for (int i=;i<=n;i++) {
memset(dep_,,sizeof dep_);
memset(que_,,sizeof que_);
int h=,t=;
que_[]=father[i]; dep_[father[i]]=; dep_[i]=-;
while (h<t) {
int cur=que_[++h];
for (int p=last[cur];p;p=pre[p]) {
if ((dep_[other[p]])||(dep_[other[p]]==-)) continue;
que_[++t]=other[p]; dep_[other[p]]=dep_[cur]+;
}
}
for (int j=;j<=n;j++) fuck_dis[i][dep_[j]]++;
}
/*
for (int i=1;i<=n;i++) {
printf("%d ",i);
for (int j=1;j<=n;j++) if (fuck_dis[i][j]) printf("%d ",fuck_dis[i][j]);
printf("\n");
}
*/
for (int i=;i<=n;i++)
for (int j=;j<=dis[i][];j++) ans+=dis_[i][j]*fuck_dis[i][j];
printf("%lld\n",ans);
fclose(stdin); fclose(stdout);
return ;
}
bzoj 3522 tree-dp 暴力的更多相关文章
- bzoj 1017 tree dp
这道题几经波折啊. 最开始和vfleaking一样,把题意理解错了,认为一个装备可能被多个装备依赖,然后想不出来,去看题解. 发现自己理解错了题意,自己想想,其实也不难想到dp[i][j][k]表示“ ...
- BZOJ 3522 DFS+DP
思路: f[]表示选1个点的 g[]表示选2个点的 dp一下 ans+=(ll)g[k]*deep[k]; g[k]+=(ll)f[k]*deep[k]; f[k]+=deep[k]; 听说有O(n) ...
- bzoj 3522 / 4543 [POI 2014] Hotel - 动态规划 - 长链剖分
题目传送门 bzoj 3522 需要root权限的传送点 bzoj 4543 快速的传送点 慢速的传送点 题目大意 给定一棵树,问有多少个无序三元组$(x, y, z)$使得这三个不同点在树上两两距离 ...
- bzoj 2212 Tree Rotations
bzoj 2212 Tree Rotations 考虑一个子树 \(x\) 的左右儿子分别为 \(ls,rs\) .那么子树 \(x\) 内的逆序对数就是 \(ls\) 内的逆序对数,\(rs\) 内 ...
- 96. Unique Binary Search Trees (Tree; DP)
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...
- HDU 4359——Easy Tree DP?——————【dp+组合计数】
Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- TYOI Day1 travel:Tree dp【处理重复走边】
题意: 给你一棵树,n个节点,每条边有长度. 然后有q组询问(u,k),每次问你:从节点u出发,走到某个节点的距离mod k的最大值. 题解: 对于无根树上的dp,一般都是先转成以1为根的有根树,然后 ...
- HDU 4359 Easy Tree DP?
Easy Tree DP? Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- C. Ilya And The Tree 树形dp 暴力
C. Ilya And The Tree 写法还是比较容易想到,但是这么暴力的写法不是那么的敢写. 就直接枚举了每一个点上面的点的所有的情况,对于这个点不放进去特判一下,然后排序去重提高效率. 注意d ...
- BZOJ.3522.[POI2014]Hotel(DP)
题目链接 BZOJ 洛谷 以为裸点分治,但数据范围怎么这么小?快打完了发现不对.. n^2做的话其实是个水题.. 枚举每一个点为根,为了不重复计算,我们要求所求的三个点必须分别位于三棵子树上. 考虑当 ...
随机推荐
- (五)hadoop系列之__集群搭建SSH无密访问多台机器
免密码ssh设置 现在确认能否不输入口令就用ssh登录localhost: $ ssh localhost 如果不输入口令就无法用ssh登陆localhost,执行下面的命令: . 并修改hosts映 ...
- ConcurrentHashMap原理分析(1.7与1.8)-put和 get 需要执行两次Hash
ConcurrentHashMap 与HashMap和Hashtable 最大的不同在于:put和 get 两次Hash到达指定的HashEntry,第一次hash到达Segment,第二次到达Seg ...
- Delphi ADOQuery多个参数重复 改编技巧
今天看了多年前的一个帖子,发现回答不合理,有些还将其归为delphi的bug.其实主要是没有灵活应用参数. ADOQUERY查询时,这样不行,结果不正确. WITH ADOQUERY1 DO BEGI ...
- hadoop跑第一个实例过程
第一次跑hadoop实例,中间经过了不少弯路,特此记录下来: 第一步:建立一个maven过程,pom.xml文件:(打包为jar包) <dependency> <groupId> ...
- [三]SpringBoot 之 热部署
如下配置 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring ...
- P2323 [HNOI2006]公路修建问题
题目描述 输入输出格式 输入格式: 在实际评测时,将只会有m-1行公路 输出格式: 输入输出样例 输入样例#1: 4 2 5 1 2 6 5 1 3 3 1 2 3 9 4 2 4 6 1 输出样例# ...
- 洛谷 P2659 美丽的序列 解题报告
P2659 美丽的序列 题目背景 GD是一个热衷于寻求美好事物的人,一天他拿到了一个美丽的序列. 题目描述 为了研究这个序列的美丽程度,GD定义了一个序列的"美丽度"和" ...
- dfs序七个经典问题(转)
我这个人不怎么喜欢写轻重链剖分和LCT 还是喜欢dfs序.括号序列之类的 毕竟线段树好写多了 然后就有了这篇转载的文章 写在这边以后有时间看看 原文链接:https://www.cnblogs.com ...
- jQuery 前端实现手机验证码
html <input id="phone" type="text" name="phone"> <input id=&q ...
- UESTC--1730
原题链接:http://acm.uestc.edu.cn/problem.php?pid=1730 分析:线段树单点更新,区间求和. #include<iostream> #include ...