hdu 4123 Bob’s Race 树形DP + 单调队列
来源:互联网 发布:linux 打开一个目录 编辑:程序博客网 时间:2024/04/30 08:19
Bob’s Race
在昨天的模拟赛中,有一种情况没想明白,就没怎么写了。今天又想了一下,其实和hdu4008很像。然后重新写了一遍就AC了,看来树形DP的题目还得好好写写。
说一下思路:分为求每个点出发的最长路和求最长区间两个阶段。关于求最长区间的可以直接采用单调队列,hdu3530便是一个求最长区间的问题。主要说一下求每个点的出发的最长路。
求最长路:两个DFS. 第一次DFS,我们以任意一个点做为根节点,我采用的是编号为1的节点,求出每个节点在根为1的情况到叶子节点的最长距离和次长距离,要求次长距离与最长距离没有公共边。这里其实就是从节点x的子节点中选出路径最长的与路径次长的。这样就保证了没有公共边。
第二次DFS:变换根节点,也即旋转。将原先非根的节点变成根,当然这里只是为了求出该点出发的最长距离。我们设现在有节点v以及其子节点u.很容易知道经过v的最长路,肯定是从v的子节点走,或者从v的父节点(以第一次DFS的根节点为根的时候)。在算u的距离的时候,我们考虑:如果v的最长路径没有经过u,很显然此时u的最长距离肯定w(u , v) +v的最长距离;假设从u出发到叶子节点的最长距离为d[u] , 当v的最长路t[v] = d[u] + w(u , v) , 此时有可能有两条距离相等的最长路,或者最长路就只有经过u的路径。在前一种情况下,我们也很容易的算的t[u] = t[v] + w , 在后一种情况下,t[u]的值要么是d[u],要么是v的次长路径,不过次长路径是为经过u子树的。分析到这里,我们就知道需要求解出那些数据才能求解出每个点出发的最长距离。在第二次DFS的时候,我们同样的需要求出每个节点出发的最长路径与不相交的次长路径。关于次长路径的计算,参看程序中的解释。
/*author : csuchenanPROG : hdu 4123LANG : C++Algorithm : 树形DP + 单调队列17csu_chenan578MS3348K3690BC++2012-09-02 17:58:07*/#include <cstdio>#include <cstring>#include <vector>#define maxn 50005#define INF 100000000#define debug 0using std::vector ;struct node{ int f ; int s ; node(int a = 0 , int b = 0) : f(a) , s(b){}};vector<node> G[maxn] ;int qmax[maxn] ;int qmin[maxn] ;int d[maxn][2] ;int t[maxn][2] ;int n ;int m ;int front ;int tail ;int head ;int rear ;inline void init(){ memset(d , 0 , sizeof(d)) ; memset(t , 0 , sizeof(t)) ; for(int i = 0 ; i <= n ; i ++){ G[i].clear() ; }}void swap(int &a , int &b){ a = a ^ b ; b = a ^ b ; a = a ^ b ;}int max(int x , int y){ return x > y ? x : y ;}void dfs1(int v , int fa){ //找出距离中最长的和次长的 for(vector<node>::size_type i = 0 ; i != G[v].size() ; i ++){ int u = G[v][i].f ; int w = G[v][i].s ; if(u==fa) continue ; dfs1(u , v) ; if( d[u][0] + w > d[v][1] ){ d[v][1] = d[u][0] + w ; } if(d[v][1] > d[v][0]){ swap(d[v][1] , d[v][0]) ; } }}void dfs2(int v , int fa){ for(vector<node>::size_type i = 0 ; i != G[v].size() ; i ++){ int u = G[v][i].f ; int w = G[v][i].s ; if(u == fa) continue ; if(t[v][0] > d[u][0] + w){ //v的最长路不经过u点, t[u][0] = t[v][0] + w ; t[u][1] = d[u][0] ; } else{ //v的最长路可能经过u点的情况 if(t[v][1] == t[v][0]){ //v的次长路与最长路是相等的, t[u][0] = t[v][0] + w ; t[u][1] = d[u][0] ; } else{ //v的次长路与最长路不相等,必定经过u if(t[v][1] + w >= d[u][0]){ t[u][0] = t[v][1] + w ; t[u][1] = d[u][0] ; } else{ t[u][0] = d[u][0] ; t[u][1] = max(t[v][1] + w , d[u][1]) ; } } } dfs2(u , v) ; }}int work(int q){ int from = 1 ; front = 1 ; head = 1 ; tail = 0 ; rear = 0 ; int ans = 0 ; for(int i = 1 ; i <= n ; i ++){ while(rear >= front && t[qmax[rear]][0] < t[i][0]) rear -- ; qmax[++ rear] = i ; while(tail >= head && t[qmin[tail]][0] > t[i][0]) tail -- ; qmin[++ tail] = i ; if(t[qmax[front]][0] - t[qmin[head]][0] > q){ if(qmax[front] < qmin[head]){ from = qmax[front] + 1 ; front ++ ; } else{ from = qmin[head] + 1 ; head ++ ; } } if(ans < i - from + 1) ans = i - from + 1 ; } return ans ;}void solve(){ dfs1(1 , 0) ; t[1][0] = d[1][0] ; t[1][1] = d[1][1] ; dfs2(1 , 0) ; if(debug){ for(int i = 1 ; i <= n ; i ++){ printf("%d %d %d\n" , i , t[i][0] , d[i][0]) ; } } int q ; int ans ; for(int i = 0 ; i < m ; i ++){ scanf("%d" , &q) ; ans = work(q) ; printf("%d\n" , ans) ; }}int main(){ while(scanf("%d%d" , &n , &m) , n||m){ int a ; int b ; int c ; init() ; for(int i = 1 ; i < n ; i ++){ scanf("%d%d%d" , &a , &b , &c) ; G[a].push_back(node(b , c)) ; G[b].push_back(node(a , c)) ; } solve() ; } return 0 ;}
- hdu 4123 Bob’s Race 树形DP + 单调队列
- hdu 4123 Bob’s Race(树形DP+单调队列)
- hdu 4123 Bob’s Race 树形dp+单调队列
- HDU 4123 Bob’s Race (树形DP + 单调队列)
- HDU 4123 Bob’s Race(树形DP + 单调队列)
- HDU 4213 Bob’s Race(树形dp+单调队列)
- 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race
- 树形DP+RMQ+单调队列(Bob’s Race HDU4123)
- hdu 4123 Bob’s Race(单调队列或者rmq)
- HDU 4123 Bob’s Race 树的直径+单调队列
- HDU 4123--Bob’s Race(树形dp)
- hdu 4123 Bob’s Race(树形DP&RMQ)
- HDU 4123 Bob’s Race(树形DP+RMQ)
- hdu 4123 Bob’s Race(树形dp+RMQ)
- HDU 4123 Bob’s Race(树形DP+RMQ)
- HDU 4123 - Bob’s Race(树形DP + RMQ)
- hdu 4123 Bob’s Race 树形DP + RMQ
- HDU 4123 Bob’s Race(树形DP,rmq)
- 黑马程序员_JavaSE基础05 之 数组的操作 求最值 排序 折半查找
- html内嵌php函数的写法
- Event Blocks for Selection Screens
- 黑马程序员五、集合框架Collection
- ubuntu --jdk1.6 安装
- hdu 4123 Bob’s Race 树形DP + 单调队列
- uva 10148 - Advertisement
- windows 7热点
- 驱动模块的加载
- hibernateTemplate的9个常用方法
- 2011-01-08 19:49 Oracle数据导入导出imp/exp sp2-0734
- Oracle权限
- C++标准转换运算符reinterpret_cast
- Cookie中value的设置问题