2014多校5(1006)hdu4916(树形DP)

本文解析了一道关于树形结构的最小值查询算法题目,通过定义特定的路径最小值来解决问题。文章详细介绍了如何利用树形DP进行有效求解,并提供了实现思路及关键代码片段。

Count on the path

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 255    Accepted Submission(s): 59


Problem Description
bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n.

Let f(a,b) be the minimum of vertices not on the path between vertices a and b.

There are q queries (ui,vi) for the value of f(ui,vi). Help bobo answer them.
 

Input
The input consists of several tests. For each tests:

The first line contains 2 integers n,q (4≤n≤106,1≤q≤106). Each of the following (n - 1) lines contain 2 integers ai,bi denoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following q lines contains 2 integer u′i,v′i (1≤ui,vi≤n).

The queries are encrypted in the following manner.

u1=u′1,v1=v′1.
For i≥2, ui=u′i⊕f(ui - 1,vi - 1),vi=v′i⊕f(ui-1,vi-1).

Note ⊕ denotes bitwise exclusive-or.

It is guaranteed that f(a,b) is defined for all a,b.

The task contains huge inputs. `scanf` in g++ is considered too slow to get accepted. You may (1) submit the solution in c++; or (2) use hand-written input utilities. 
 

Output
For each tests:

For each queries, a single number denotes the value.
 

Sample Input
4 1 1 2 1 3 1 4 2 3 5 2 1 2 1 3 2 4 2 5 1 2 7 6
 

Sample Output
4 3 1

题意:查询不在a和b路径上标号最小的点

思路:首先以1节点为根将整颗树定形,分路径经过节点1和不经过讨论

1.路径不经过节点1,则节点1就是答案

2.路径经过节点1,那么令path[u]为不在u到1节点路径上的最小标号节点,那么在u和v两种情况中取较小的即可

处理起来有点麻烦,看代码吧~

child[u][3]表示u的前三小的子树

mintree[u]表示以u为根的子树中节点的最小标号

vis[u]表示u在1的哪颗子树中

belong[u]表示u所属于的1的子树中最小节点的标号

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define maxn 1000010
#define INF 2000000
int n,q1;
int head[maxn];
int edge[maxn<<1];
int next[maxn<<1];
int q[maxn];
int fa[maxn];
int mintree[maxn];
int child[maxn][3];
int path[maxn];
int vis[maxn];
int belong[maxn];
int d;

int mini(int x,int y)
{
    return x=0;i--)
    {
        int o=q[i];
        mintree[o]=mini(o,child[o][0]);
        child[fa[o]][2]=mintree[o];
        sort(child[fa[o]],child[fa[o]]+3);
    }

    rear=0;
    front=0;
    int dd=0;

    vis[1]=-1;

    for(i=head[1];i!=-1;i=next[i]){
        path[edge[i]]=INF;
        q[rear++]=edge[i];
        vis[edge[i]]=dd++;
        belong[edge[i]]=mintree[edge[i]];
    }

    while(front
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值