点分治学习笔记(2) tree
来源:互联网 发布:人工智能的未来下载 编辑:程序博客网 时间:2024/05/16 14:14
今天做点分治的题,调了1个多小时,发现之前对点分治的理解是有一些偏差的。
dis【v】求出来的是那个点到根的距离。
solve不断分治。cal计算其中经过根节点的所有路径,我们在cal的时候把根节点也统计进去的话,枚举的时候就算上了到根节点的路径。不统计根节点的话,就没有计算到根节点的路径。所以要单独处理。
还有一点是,多组数据我又没有初始化边数组!小ly你能不能长点记性啊,你忘了你NOIP暴力怎么写炸的了?多组数据的题,加进去的边要初始化,head数组和cnt也要初始化。能不能记住啊。。你NOIP犯这么蠢的错误已经留下一次遗憾了,难道你还要把错误继续犯到省选?下次再错出去跑十圈。。
还有就是,对于u节点我们统计了所有他的答案。但这里面有来自一个子树的点贡献的答案。这部分答案,我们再减去就好了。减去的时候直接减就可以,因为整体答案本来是重复的,你减去的部分也是重复的,减完就不重复了(这段估计只有我能看懂)。。
附调了一个多小时的题目:
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 vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
#include<iostream>#include<cstring>#include<time.h>#include<cmath>#include<stdio.h>#include<vector>#include<algorithm>using namespace std;const int MAXN=1e5+5;struct edge{ int to,next,w;}e[MAXN<<1];int head[MAXN],cnt=0,anss=0;inline void add(int u,int v,int w){e[++cnt]=(edge){v,head[u],w},head[u]=cnt;}vector<int>d;int n,m,k;int size[MAXN],f[MAXN],dis[MAXN],rt=0,sum;bool vis[MAXN];void dfs1(int u,int fa){ size[u]=1; f[u]=0; for(int i=head[u];i;i=e[i].next){ int v=e[i].to,w=e[i].w; if(vis[v]||v==fa)continue; dfs1(v,u); size[u]+=size[v]; f[u]=max(f[u],size[v]); } f[u]=max(f[u],sum-size[u]); if(f[u]<f[rt])rt=u;}int dfs2(int u,int fa){ int ans=0; size[u]=1;// cout<<dis[u]<<endl; d.push_back(dis[u]);// if(dis[u]<=k)ans++; for(int i=head[u];i;i=e[i].next){ int v=e[i].to,w=e[i].w; if(v==fa||vis[v])continue; dis[v]=dis[u]+w; ans+=dfs2(v,u); size[u]+=size[v]; } return ans;}int cal(int u,int num){ int ans=0; d.clear(); dis[u]=num; d.push_back(dis[u]); for(int i=head[u];i;i=e[i].next){ int v=e[i].to,w=e[i].w; if(vis[v])continue; dis[v]=dis[u]+w; ans+=dfs2(v,u); }// cout<<d.size()<<" "; int l=0,r=d.size()-1; sort(d.begin(),d.end()); while(l<r){ while(l<r&&d[l]+d[r]>k)r--; ans+=r-l; l++; }// cout<<ans<<endl; return ans;}void solve(int u){// cout<<u<<"ok"<<endl; anss+=cal(u,0); vis[u]=1; for(int i=head[u];i;i=e[i].next){ int v=e[i].to,w=e[i].w; if(vis[v])continue; anss-=cal(v,w); f[0]=sum=size[v]; dfs1(v,rt=0); solve(rt); }}int main(){ while(scanf("%d%d",&n,&k)){ memset(e,0,sizeof(e)); memset(head,0,sizeof(head));//小ly你能不能长点记性啊。。 cnt=0; if(!n&&!k) return 0; memset(vis,0,sizeof(vis)); d.clear(); for(int i=1;i<n;i++){ int tem1,tem2,tem3; scanf("%d%d%d",&tem1,&tem2,&tem3); add(tem1,tem2,tem3);add(tem2,tem1,tem3); } anss=0; f[0]=sum=n; dfs1(1,rt=0); solve(rt); printf("%d\n",anss); } return 0;}
- 点分治学习笔记(2) tree
- 点分治学习笔记(1)
- poj1741 Tree(点分治)
- [POJ1741]Tree(点分治)
- [bzoj1468]Tree(点分治)
- poj1741 tree(点分治)
- [学习笔记] 点分治学习笔记
- hdu4812 D Tree(点分治)
- POJ 题目1747 Tree(点分治)
- POJ 1741 Tree(点分治)
- POJ 1741 Tree(树+点分治)
- POJ-1471-Tree(点分治)
- poj Tree(树的点分治)
- 【POJ 1741】Tree (树上点分治)
- POJ1741 Tree (树形dp+点分治)
- [POJ 1741] Tree (点分治)
- bzoj 1468: Tree (点分治)
- hdu 5571 tree (动态点分治)
- 要点提炼|开发艺术之View
- java之面向对象3
- uip协议栈移植的原理图、pcb、原理图库、pcb库
- 剑指offer——面试题61:按之字形顺序打印二叉树
- CUDA 矩阵编写 小试牛刀
- 点分治学习笔记(2) tree
- LintCode_539_移动零
- 关于SQL宽字节注入的学习
- 利用优先队列PriorityQueue实现Prim算法
- 2017 年成为 Linux 专家的 4 个热门技能
- socketserver模块
- 程序编译过程
- Linux多线程编程之设置线程属性,设置线程分离属性
- Python 面试问答 Top 25