这道题的题意其实有点略晦涩,定义f(a,b)为 minimum of vertices not on the path between vertices a and b. 其实它加一个minimum index of vertices应该会好理解一点吧。看了一下题解,还有程序,才理清思路。

首先比较直接的是如果两点的路径没有经过根节点1的话,那么答案就直接是1,否则的话就必然有从根节点出发的两条路径,题解里说的预处理出f[u]表示不在根节点到u的路径上的点的最小值,然后取f[u]和f[v]的最小值看了我半天。因为如果是这样的话,那么下面这个图不就可以轻易cha掉这种做法?

1->2  1->3  2->4  4->6  4->7  3->5  5->8  5->9

询问(6,8)的时候显然f(6)是3,f(8)是2,那么输出的答案就会是2,但实际上应该输出的是7。

后来仔细探究了才发现,f[u]存的只是  从不在根节点到u的路径的最小值(其中不包括根节点到别的子节点的路径),换言之上面的f[6]里只存了7,f[8]里只存了9,所以min(7,9)=7。

但是这个时候我们可能就会出错了,因为如果根节点如果连出去有第三条路径的话,那么这条路径的最小值我们是没有包含到的,所以对于根节点我们要存它最小值的子树,还有也要存对于每个节点它来自于哪个子树。

剩下的就是一个类似树dp的过程了。

然后题目还温馨提示了可能会超时,可能要写个输入挂什么的,所以写邻接表的可能都不能写vector的形式了吧。

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; #define maxn 1005000
#define inf 0x3f3f3f3f int child[maxn][4];
int subtree[maxn];
int path[maxn];
int fa[maxn];
int bel[maxn];
int que[maxn];
int qh, qt;
int n, nQ; int head[maxn];
int nxt[maxn<<1];
int vv[maxn<<1];
int tot; void add_Edge(int u,int v)
{
vv[tot] = v; nxt[tot] = head[u]; head[u] = tot++;
} void bfs()
{
qh = qt = 0;
que[qt++] = 1; fa[1] = -1;
while (qh < qt){
int u = que[qh++];
for (int i = head[u]; ~i; i=nxt[i]){
int v = vv[i];
if (v == fa[u]) continue;
fa[v] = u;
que[qt++] = v;
}
}
for (int i = 0; i <= n; ++i){
for (int j = 0; j < 4; ++j){
child[i][j] = inf;
}
}
for (int i = n - 1; i >= 0; --i){
int u = que[i]; subtree[u] = u;
for (int j = head[u]; ~j; j=nxt[j]){
int v = vv[j];
if (v == fa[u]) continue;
child[u][3] = subtree[v];
sort(child[u], child[u] + 4);
}
subtree[u] = min(subtree[u], child[u][0]);
} qh = qt = 0;
for (int i = head[1]; ~i; i=nxt[i]){
int v = vv[i];
que[qt++] = v;
bel[v] = subtree[v];
path[v] = inf;
}
while (qh < qt){
int u = que[qh++];
for (int i = head[u]; ~i; i=nxt[i]){
int v = vv[i];
if (v == fa[u]) continue;
bel[v] = bel[u];
if (subtree[v] == child[u][0]){
path[v] = min(path[u], child[u][1]);
}
else{
path[v] = min(path[u], child[u][0]);
}
que[qt++] = v;
}
path[u] = min(path[u], child[u][0]);
}
} int query(int qu, int qv){
if (qu > qv) swap(qu, qv);
if (qu != 1 && bel[qu] == bel[qv]) return 1;
int i = 0;
while (child[1][i] == bel[qu] || child[1][i] == bel[qv]){
i++;
}
int ret = qu == 1 ? path[qv] : min(path[qu], path[qv]);
ret = min(ret, child[1][i]);
return ret;
} inline void scan(int &n)
{
char cc;
for (; cc = getchar(), cc<'0' || cc>'9';);
n = cc - '0';
for (; cc = getchar(), cc >= '0'&&cc <= '9';)
n = n * 10 + cc - '0';
} int main()
{
while (cin >> n >> nQ){
tot = 0; memset(head, -1, sizeof(head));
int ui, vi;
for (int i = 0; i < n - 1; ++i){
//scan(ui); scan(vi);
scanf("%d%d", &ui, &vi);
add_Edge(ui, vi);
add_Edge(vi, ui);
}
bfs();
int last = 0;
for (int i = 0; i < nQ; ++i){
//scan(ui); scan(vi);
scanf("%d%d", &ui, &vi);
ui ^= last; vi ^= last;
printf("%d\n", last=query(ui, vi));
}
}
return 0;
}

HDU4916 Count on the path(树dp??)的更多相关文章

  1. hdu4916 Count on the path

    调了好久.... •把树视为以1为根的有向树,然后将1删除 •原树变为一个森林,并且任一棵树的根节点均为原树中1的子节点 •只需要考虑最小编号前3小的三棵树 •记f[x][y]为去掉x和y两棵树后的最 ...

  2. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

  3. Count on the path

    Count on the path Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  4. CF456D A Lot of Games (字典树+DP)

    D - A Lot of Games CF#260 Div2 D题 CF#260 Div1 B题 Codeforces Round #260 CF455B D. A Lot of Games time ...

  5. Codeforces 219D. Choosing Capital for Treeland (树dp)

    题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...

  6. HDU4276 The Ghost Blows Light SPFA&&树dp

    题目的介绍以及思路完全参考了下面的博客:http://blog.csdn.net/acm_cxlove/article/details/7964739 做这道题主要是为了加强自己对SPFA的代码的训练 ...

  7. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  8. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  9. bzoj 3572世界树 虚树+dp

    题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...

随机推荐

  1. C 函数可变参数

    C 函数可变参数 C 语言中用 ... 表示可变参数,例如: void fun(int x ...) 头文件 cstdarg.h 中包含可变参数类型va_list和处理可变参数的三个宏: va_lis ...

  2. 通过shell脚本获取日期,并赋给变量

    通过shell获取当前8位日期,并赋给变量,并且使用变量作为文件名,建立文件夹 代码如下: ls_date=`date +%Y%m%d` mkdir ${ls_date} 上面两句代码虽然简单 但是在 ...

  3. ios开发--常用宏定义(部分转)

    1.release时,屏蔽log #if defined (DEBUG) && DEBUG == 1 #else #define NSLog(...) {}; #endif #if d ...

  4. MongoDB学习笔记-查询

    MongoDB中使用find或findOne函数执行查询 find函数 db.c.find()--查询集合c所有 db.c.find({“name”:”zhangsan”}) 注意:查询条件的值必须是 ...

  5. 按键精灵实现自动退出的MsgBox消息框

    要实现自动倒计时退出的消息框,代码如下: Set wsh = CreateObject("WScript.Shell") wsh.popup "设置完毕,3秒后自动退出! ...

  6. Android BLE API: GATT Notification not received

    When setting the value to the descriptor instead of putting descriptor.setValue(BluetoothGattDescrip ...

  7. Excel下用SQL语句实现AVEDEV函数功能

    Excel下AVEDEV函数返回一组数据点到其算术平均值的绝对偏差的平均值. AVEDEV 是对一组数据中变化性的度量.最常见的应用就是统计平均分差. 但是如果在Excel中写SQL进行一些复杂的统计 ...

  8. iframe 传值问题

    当一个页面中插入了iframe或者由不同的框架组成(fieldset)时,这种情况下,需要处理的业务逻辑比较常见的就是数据进行交互了 1.页面中插入了iframe情况 由于页面中插入了iframe,那 ...

  9. 修改Input中Placeholder默认提示颜色(兼容)

    input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: #f00; } input:-moz-pl ...

  10. 【Search for a Range】cpp

    题目: Given a sorted array of integers, find the starting and ending position of a given target value. ...