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做的话其实是个水题.. 枚举每一个点为根,为了不重复计算,我们要求所求的三个点必须分别位于三棵子树上. 考虑当 ...
随机推荐
- 一次性无重复配置VS项目插件属性的方法
在VS中需要使用opencv开源库或mysql等数据库时,为了能使用开源库或数据库的语言,需要添加库文件和包含目录等等.然而直接在[解决方案管理器]-->属性中配置的话,写下一个项目(解决方案) ...
- java catch 捕获异常后会产生一个实例对象 该对象能使用父类的方法
- 包装类 integer 当做 list的参数时候 会出现无法删除成功的现象
- bzoj1031-字符加密
环的问题,经典方法倍长串,求出后缀数组,扫一次sa,如果sa[i]小于等于n,那么就输出这个字符串结尾的位置(即s[sa[i]+n-1]). 代码 #include<cstdio> #in ...
- IDEA使用switch传入String编译不通过
今天在使用IDEA的时候,用到switch分支语句,传入String参数的时候一直报错,下面是源码报错截图: 看错误提示并没有提到switch支持String类型,不过ava1.7之后就支持Strin ...
- javascript如何封装函数
通常写js组件开发的,都会用到匿名函数的写法去封装一个对象,与外界形成一个闭包的作用域.封装,全天下漫天遍野的封装,JQuery,EXT和Prototype.js封装的是javascript,jQue ...
- BZOJ4878 挑战NP-Hard(dfs树)
既然是二选一,考虑两个问题有什么联系.题面没有说无解怎么办,所以如果不存在经过k条边的简单路径,一定存在k染色方案.考虑怎么证明这个东西,我们造一棵dfs树.于是可以发现如果树深>k(根节点深度 ...
- BZOJ3622 已经没有什么好害怕的了(动态规划+容斥原理)
显然可以转化为一个阶梯状01矩阵每行每列取一个使权值和为k的方案数.直接做不可做,考虑设f[i][j]为前i行权值和至少为j,即在其中固定了j行选1的方案数.设第i行从1~a[i]列都是1且a[i]+ ...
- XML格式化加载的时候提示Content is not allowed in prolog. Nested exception: Content is not allowed in prolog
原因:原本是.xml文件格式的内容,被你用右键,文本编辑,保存,导致格式不认了. 解决方法:下载个notepad+ 工具,用这工具打开,修改,编辑,保存,即可被继续认作xml格式.
- 【刷题】BZOJ 2555 SubString
Description 懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支 ...