[bzoj1468]Tree(点分治)
来源:互联网 发布:苹果笔记本软件下载 编辑:程序博客网 时间:2024/05/16 16:57
传送门
点分治这个算法一开始学的时候真的觉得这就是玄学,因为按道理来说,这样递归应该是
关于这个题,就是每次找重心,以重心为根dfs每个点到重心的距离,然后统计经过重心的路径,然后删除重心(打个标记),继续递归执行重心的每棵子树。
统计重心的答案时,可以将每个点到重心的距离排个序,左右两个指针扫,可以
然后得出的答案就是错误的。
为什么呢?我们可以自己手造一组数据,画出图来,然后统计答案时我们暴力统计(就是不要拿指针扫),看看答案中都是什么路径。
然后就发现,有路径多次被统计,而且第一次统计的时间还是在这两个点在同一棵子树中时就被统计了。
为什么会出现这种情况呢?看这张图,这就是那个被重复统计的路径。
图片中数字表示路径的经过顺序,箭头表示路径方向。
很明显,如果图上这条路的总长不超过k,那么毫无疑问,一号点和五号点会被统计两次,而图上这条路径明显不符合题意,不可以被统计,那么我们只要再减去这些路径就好了,具体可以看我的代码。
然后就是要多注意细节,点分治细节比较多。
代码:
/************************************************************** Problem: 1468 User: stone41123 Language: C++ Result: Accepted Time:716 ms Memory:3324 kb****************************************************************/#include<bits/stdc++.h>#define ll long longusing namespace std;inline int read(){ int x=0;char ch=' ';int f=1; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f;}struct edge{ int to,next,w;}e[80001];int n,tot,root;ll k;int head[40001];inline void addedge(int x,int y,int l){ e[++tot].to=y;e[tot].next=head[x];e[tot].w=l;head[x]=tot;}int size[40001],vis[40001],mx,sz;ll dis[40001],q[40001],l,r;void getroot(int x,int fa){ size[x]=1;int num=0; for(int i=head[x];i;i=e[i].next){ int u=e[i].to; if(u==fa||vis[u])continue; getroot(u,x); size[x]+=size[u]; num=max(num,size[u]); } num=max(num,sz-size[x]); if(num<mx){ mx=num;root=x; }}void getdis(int x,int fa){ q[++r]=dis[x]; for(int i=head[x];i;i=e[i].next){ int u=e[i].to; if(u==fa||vis[u])continue; dis[u]=dis[x]+e[i].w; getdis(u,x); }}ll calc(int x,int v){ r=0; dis[x]=v; getdis(x,0); ll sum=0; l=1; sort(q+1,q+r+1); while(l<r){ if(q[l]+q[r]<=k)sum+=r-l,l++; else r--; } return sum;}ll ans;void dfs(int x){ ans+=calc(x,0); vis[x]=1; for(int i=head[x];i;i=e[i].next){ int u=e[i].to; if(vis[u])continue; ans-=calc(u,e[i].w); sz=size[u]; mx=0x3f3f3f3f; getroot(u,0); dfs(root); }}int main(){ n=read(); for(int i=1;i<n;i++){ int x=read(),y=read(),l=read(); addedge(x,y,l);addedge(y,x,l); } k=read(); sz=n; mx=0x3f3f3f3f; getroot(1,0); dfs(root); printf("%lld",ans); return 0;}
阅读全文
0 0
- [bzoj1468]Tree(点分治)
- bzoj1468: Tree 点分治
- 【bzoj1468】【Tree】【点分治】
- bzoj1468 tree 点分治
- bzoj1468 Tree 点分治
- [BZOJ1468]Tree 点分治
- 树上点分治模板bzoj1468
- POJ1741 Tree(BZOJ1468)
- 【BZOJ1468】Tree
- bzoj1468 Tree
- 【bzoj1468】Tree
- bzoj1468: Tree
- bzoj1468 Tree
- poj1741 Tree(点分治)
- [POJ1741]Tree(点分治)
- poj1741 tree(点分治)
- hdu4812 D Tree(点分治)
- POJ 题目1747 Tree(点分治)
- 关于python的一些特性
- 经典回溯算法之n皇后问题
- 解决 CocoaPods was not able to update the `master` repo
- JAVA NIO(六):读取10G的文件其实很容易
- 栈和队列---生成窗口最大值数组
- [bzoj1468]Tree(点分治)
- 寒武纪一面
- Fragment的一个简单实现+EditText的监听事件
- TensorFlow深度学习,一篇文章就够了
- mysql高可用MHA
- STM32串口中断卡死主循环问题分析
- Binary Search Tree--Data Structure
- java使用链表实现队列
- QL的四种连接-左外连接、右外连接、内连接、全连接