思路:我们定义一个dfn[i],Maxndfn[i]来确定节点i的访问次序,以及其子节点的最大访问次序。那么另一个节点是其子树的节点当且仅当dfn[j]>=dfn[i]&&dfn[j]<=Maxdfn[i];

这是就可以先以1为根,dfs找出所有节点最小儿子,次小儿子,以及最小子孙,次小子孙。

剩下就可以分情况:

对于x,y:

1.若与y相连的边数为1,那么一定就是no answers!。

2.对于最小儿子节点的询问:

(1)若x是y的子节点,那么如果x包含在y的最小儿子子树中,那么就答案就是次小儿子与其父节点中较小的,否则就是最小儿子与其父节点中较小的。

(2)若y是x点子节点(设不是y的子节点的都是其根节点),那么就直接输出最小儿子。

3.对于最小子孙节点的询问:

(1)若x是y的子节点,那么如果x包含在y的最小子孙所在子树中(小于以y为根的子树),那么就答案就是次小子孙,否则就是最小子孙,其实这只设和y为1的情况,若y为其它节点,其最小子孙直接就是1。

(2)若y是x点子节点(设不是y的子节点的都是其根节点),那么就直接输出最小子孙。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#define Maxn 100010
#define inf 0x7fffffff
using namespace std;
int son[Maxn],nson[Maxn],der[Maxn],nder[Maxn],n,q,dfn[Maxn],Maxdfn[Maxn],lab,dp[Maxn],road[Maxn],father[Maxn];
vector<int> head[Maxn];
void init()
{
int i;
memset(son,,sizeof(son));
memset(nson,,sizeof(nson));
memset(der,,sizeof(der));
memset(nder,,sizeof(nder));
memset(dfn,,sizeof(dfn));
memset(father,,sizeof(father));
memset(dp,,sizeof(dp));
memset(road,,sizeof(road));
memset(Maxdfn,,sizeof(Maxdfn));
lab=;
for(i=;i<=n;i++)
head[i].clear();
}
void add(int u,int v)
{
head[u].push_back(v);
head[v].push_back(u);
}
void dfs(int u,int f)
{
int i,v,si;
dfn[u]=Maxdfn[u]=++lab;
dp[u]=u;
son[u]=nson[u]=der[u]=nder[u]=inf;
si=head[u].size();
for(i=;i<si;i++)
{
v=head[u][i];
if(v==f)
continue;
dfs(v,u);
dp[u]=min(dp[u],dp[v]);
Maxdfn[u]=max(Maxdfn[u],Maxdfn[v]);
if(v<son[u])
{
nson[u]=son[u];
son[u]=v;
}
else
{
if(v<nson[u])
nson[u]=v;
}
if(der[u]>dp[v])
{
nder[u]=der[u];
der[u]=dp[v];
road[u]=v;
}
else
if(nder[u]>dp[v]) nder[u]=dp[v];
}
father[u]=f;
}
int main()
{
int i,j,a,b,t,x,y;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&q);
for(i=;i<n;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
dfs(,);
for(i=;i<=q;i++)
{
scanf("%d%d",&x,&y);
int ans1,ans2;
if(head[y].size()==)
{
puts("no answers!");
continue;
}
if(dfn[x]<dfn[y]||dfn[x]>Maxdfn[y])
printf("%d %d\n",son[y],der[y]);
else
{
if(dfn[x]>=dfn[son[y]]&&dfn[x]<=Maxdfn[son[y]])
ans1=nson[y];
else
ans1=son[y];
if(dfn[x]>=dfn[road[y]]&&dfn[x]<=Maxdfn[road[y]])
ans2=nder[y];
else
ans2=der[y];
if(y!=) ans1=min(ans1,father[y]),ans2=;
printf("%d %d\n",ans1,ans2);
}
}
printf("\n");
}
return ;
}

hdu 4008 树形dp的更多相关文章

  1. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  2. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  3. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  4. HDU 2196树形DP(2个方向)

    HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...

  5. HDU 1520 树形DP入门

    HDU 1520 [题目链接]HDU 1520 [题目类型]树形DP &题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知 ...

  6. codevs 1380/HDU 1520 树形dp

    1380 没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 回到问题 题目描述 Description Ural大学有N个职员 ...

  7. HDU 5834 [树形dp]

    /* 题意:n个点组成的树,点和边都有权值,当第一次访问某个点的时候获得利益为点的权值 每次经过一条边,丢失利益为边的权值.问从第i个点出发,获得的利益最大是多少. 输入: 测试样例组数T n n个数 ...

  8. hdu 4267 树形DP

    思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零.那么对剩下的图就可以直接树形dp求解了. #include<iostream> #include<al ...

  9. hdu 4607 (树形DP)

    当时比赛的时候我们找出来只要求出树的最长的边的节点数ans,如果要访问点的个数n小于ans距离直接就是n-1 如果大于的话就是(n-ans)*2+ans-1,当时求树的直径难倒我们了,都不会树形dp ...

随机推荐

  1. Android实例-读取设备联系人(XE8+小米2)

    相关资料: http://www.colabug.com/thread-1071065-1-1.html 结果: 1.将权限打开Read contacts设置为True,不然报图一的错误. 2.搜索空 ...

  2. ocp 1Z0-051 23-70题解析

    23. Examine thestructure proposed for the TRANSACTIONS table: name Null Type TRANS_ID NOT NULLNUMBER ...

  3. Codeforces Round #352 (Div. 2) D. Robin Hood (二分答案)

    题目链接:http://codeforces.com/contest/672/problem/D 有n个人,k个操作,每个人有a[i]个物品,每次操作把最富的人那里拿一个物品给最穷的人,问你最后贫富差 ...

  4. SQLite多线程写锁文件解决方案

    在sqlite编程中多线程同时写时会出现异常,我写了个类来解决这个问题. 思路很简单,就是在开始写操作时,记下写操作的托管线程id,表示目前有线程正在做写操作:其他线程来写时,需要先检测是否有进程正在 ...

  5. Windows下sqlmap的使用_01

    环境:win8.1 64位    一.下载 首先,需下载SqlMap以及适用于Windows系统的Python.下载地址如下:   1.1.SqlMap下载地址:https://github.com/ ...

  6. mysql case when 条件过滤

    [1].[代码] 使用CASE WHEN进行字符串替换处理 跳至 [1] [2] [3] [4] ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 2 ...

  7. 十,选择cfee编辑器并学会调试程序。以及结束语。

    为什么推荐用cfree呢?因为我认为这个编辑器界面友好,用起来方便. 你也许会问,调试程序是什么? 那么下面思考几个问题:对于前面讲的分支结构和循环结构有点不懂怎么办?如果写的程序语法没有错误但是运算 ...

  8. GMT、UTC、PDT 时间是什么?Linux下如何调整时区

       今天碰到一个时区配置问题,如果服务器时区配置不对,很可能在使用date相关函数时会出现莫名其妙的错误,现将相关时区说明及LINUX下调整时区方法记录如下,以做备忘. GMT GMT 是 Gree ...

  9. delphi 使用进度条查看浏览器状态

    使用进度条查看浏览器状态     procedure TForm1.WebBrowser1ProgressChange(ASender: TObject; Progress,  ProgressMax ...

  10. Android 实现书籍翻页效果----完结篇

    By 何明桂(http://blog.csdn.net/hmg25) 转载请注明出处 之前由于种种琐事,暂停了这个翻页效果的实现,终于在这周末完成了大部分功能,但是这里只是给出了一个基本的雏形,没有添 ...