poj4003 树形dp, rmq_st
来源:互联网 发布:steam淘宝礼物退款 编辑:程序博客网 时间:2024/05/03 05:50
很综合的题目,出得非常好
第一个问题是求以树中的每个节点为起点所能走的最长路:
首先,求出各个点的最长路,次长路,以及最长路的后继节点,再据此得到答案
第二个问题,需要rmq,并且维护一个队列,只要满足条件,队尾添加新元素,不然同时弹出队头
注意!dfs函数中tmp2为根走另一分支所得次长路,与最长路无公共路径!
#include <iostream>using namespace std;struct gtype { int y,d,next;}g[100010];int first[50010],tot,x,y,d,s[50010],a[50010][4],n,m,q;int MIN[50001][20],MAX[50001][20];void add(int x,int y,int d) { tot++; g[tot].y = y; g[tot].d = d; g[tot].next = first[x]; first[x] = tot;}int dfs(int x,int fa) { int tmp1 = 0, tmp2 = 0, vx = 0; for (int t=first[x];t!=-1;t=g[t].next) { int y = g[t].y; if (y==fa) continue; int tmp = g[t].d + dfs(y, x); if (tmp > tmp1) { tmp2 = tmp1; tmp1 = tmp; vx = y; } else if (tmp > tmp2) tmp2 = tmp; } a[x][0] = vx; a[x][1] = tmp1; a[x][2] = tmp2; return tmp1;} void find(int x,int fa,int ans) { int vx = a[x][0]; int tmp1 = a[x][1]; int tmp2 = a[x][2]; if (ans > tmp1) { tmp2 = tmp1; tmp1 = ans; vx = 0; } else if (ans > tmp2) tmp2 = ans; s[x-1] = tmp1; for (int t=first[x];t!=-1;t=g[t].next) { int y = g[t].y; if (y==fa) continue; if (y==vx) find(y,x,tmp2+g[t].d); else find(y,x,tmp1+g[t].d); }}int max(int x,int y) { return s[x]>s[y]?x:y;}int min(int x,int y) { return s[x]>s[y]?y:x;}void ST() { int i,j; for (i=0;i<=n;i++) MIN[i][0]=MAX[i][0]=i; for (j=1;1<<j<=n;j++) for (i=0;i+(1<<j)-1<n;i++) { MIN[i][j]=min(MIN[i][j-1],MIN[i+(1<<(j-1))][j-1]); MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<(j-1))][j-1]); } }int RMQ(int i,int j,int x) {//询问区间[i,j],x==1返回最大值下标,否则返回最小值下标 if (i>j) { i^=j;j^=i;i^=j; } int k=0; while (i+(1<<k)<j-(1<<k)+1) k++; if(x==1) return max(MAX[i][k],MAX[j-(1<<k)+1][k]); return min(MIN[i][k],MIN[j-(1<<k)+1][k]);}int maxi(int a,int b) { if (a>b) return a; else return b;}int main() { while (scanf("%d%d",&n,&m)) { if (n==0 && m==0) break; tot = 0; memset(g,0,sizeof(g)); memset(first,-1,sizeof(first)); for (int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&d); add(x,y,d); add(y,x,d); } dfs(1,0); find(1,0,0); ST(); for (int i=1;i<=m;i++) { scanf("%d",&q); int head = 1, tail = 1, ans = 0; while (tail <= n) { int tmp1 = s[RMQ(head-1,tail-1,0)]; int tmp2 = s[RMQ(head-1,tail-1,1)]; if (tmp2-tmp1<=q) { tail++; ans = maxi(ans,tail-head); } else { head++;tail++; } } printf("%d\n",ans); } } return 0;}
- poj4003 树形dp, rmq_st
- RMQ_st
- RMQ_st
- RMQ_ST
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形DP
- 树形DP
- 树形DP
- 树形dp
- 树形dp
- 树形dp
- 树形dp
- 树形DP
- oracle 管理
- QT:不规则窗口的实现
- 非递归合并排序
- 【動態規劃】打水漂
- 对enum的探讨
- poj4003 树形dp, rmq_st
- linux驱动程序设计环境搭建
- Android中的WebView进行直接加载网页
- atexit函数小结和静态对象析构
- 发现一个问题 搞了半天啊 jQuery 属性过滤问题
- 点的法向量计算
- Android监听SMS发送状态并获取短信服务中心号码
- Shell脚本编程的常识
- 锂电池充电电路原理 锂电池充电电路设计