这道题的题意其实有点略晦涩,定义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. 远程连接数据库(通过pgAdmin)

    1.编辑/var/lib/pgsql/data/pg_hba.conf,增加语句  host all all 192.168.105.225/36 trust 让数据库接受网络 192.168.105 ...

  2. Python学习教程(learning Python)--1.1Python程序设计流程

    Python程序设计与其他高级语言程序设计流程基本一致     step1 程序设计     step2 编写Python代码     setp3 Python语句语法纠错     step4 测试程 ...

  3. 使用ImageLoader实现图片异步加载

    注:下面使用的是包:1.8.4,其他版本包的,DisplayImageOptions defaultOptions和 ImageLoaderConfiguration config2配置不一样,请看官 ...

  4. JavaScript高级程序设计之EventUtil

    简单的通用事件方法 var EventUtil = { getEvent: function (e) { return e || window.event; }, getTarget: functio ...

  5. JavaScript高级程序设计之基本包装类型

    为便于操作基本类型值,ECMAScript提供了3个特殊的引用类型:Boolean, Number 和 String // 字符串怎么会有方法呢 var str1 = "some text& ...

  6. Tornado服务器的学习

    Tornado就是我们在 FriendFeed 的 Web 服务器及其常用工具的开源版本.Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞 ...

  7. wordpress nginx 开启链接为静态

    使用固定连接里的自定义 /%postname%/ 日志标题的缩略版本(日志/页面编辑界面上的日志别名).因此“This Is A Great Post!”在URI中会变成this-is-a-great ...

  8. 自学asp.net mvc(一)

    之前一直做asp.net的webform,现在想学习一下mvc,把自学中遇到的问题记录到博客. 一.codeplex上托管代码 1. 2. 3. 4. 5. 6. 7. 8. 9.

  9. xml数据读 swift

    // // ViewController.swift // xml读写 // // Created by mac on 15/7/14. // Copyright (c) 2015年 fangyuha ...

  10. C++设计模式系列

    该系列主要总结了使用C++来实现各种设计模式,并结合实际的案例来分析如何使用,以及在什么场合下使用设计模式.以下是该系列所有文章的链接.希望对大家有帮助. C++设计模式——简单工厂模式 C++设计模 ...