HDU4916 Count on the path(树dp??)
这道题的题意其实有点略晦涩,定义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??)的更多相关文章
- hdu4916 Count on the path
调了好久.... •把树视为以1为根的有向树,然后将1删除 •原树变为一个森林,并且任一棵树的根节点均为原树中1的子节点 •只需要考虑最小编号前3小的三棵树 •记f[x][y]为去掉x和y两棵树后的最 ...
- 【HDU 5647】DZY Loves Connecting(树DP)
pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...
- Count on the path
Count on the path Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 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 ...
- Codeforces 219D. Choosing Capital for Treeland (树dp)
题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...
- HDU4276 The Ghost Blows Light SPFA&&树dp
题目的介绍以及思路完全参考了下面的博客:http://blog.csdn.net/acm_cxlove/article/details/7964739 做这道题主要是为了加强自己对SPFA的代码的训练 ...
- Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)
[题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- bzoj 3572世界树 虚树+dp
题目大意: 给一棵树,每次给出一些关键点,对于树上每个点,被离它最近的关键点(距离相同被标号最小的)控制 求每个关键点控制多少个点 分析: 虚树+dp dp过程如下: 第一次dp,递归求出每个点子树中 ...
随机推荐
- python 核心编程第二版 课后习题 第11章
11-3 函数.在这个练习中,我们将实现 max()和 min()内建函数. (a) 写分别带两个元素返回一个较大和较小元素,简单的 max2()核 min2()函数.他们应该可以用任意的 pytho ...
- ED/EP系列5《消费指令》
1. 消费交易 消费交易允许持卡人使用电子存折或电子钱包的余额进行购物或获取服务. 特点: 1) --可以在销售点终端(POS)上脱机进行 2) --使用电子存折进行的消费交易必须提交个人识别码(PI ...
- hdu 5210 Delete
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5210 简单题如下: #include<algorithm> #include<ios ...
- @property @synthesize的含义以及误区。
@property的作用是定义属性,声明getter,setter方法.(注意:属性不是变量) @synthesize的作用是实现属性的,如getter,setter方法. 在声明属性的情况下如果重写 ...
- dev 激活没有权限问题
用管理员身份打开 Microsoft Visual Studio 2010-->Visual Studio Tools-->Visual Studio 命令提示(2010) 然后输入一下命 ...
- c/c++常用代码--udp多播
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <winsock.h ...
- jquery页面刷新reload
今天知道了jquery页面刷新的一个方法,很简单的一句: window.location.reload()刷新当前页面,不得不说我jquery学的很糟糕,明明都学过,但是等用到的时候就想不起来了.不过 ...
- Java实现Socket之WhoisClient
Java实现Socket之WhoisClient 代码内容 从常用的whois服务器的43号端口得到对应域名的所有注册信息并显示出来 代码实现 /* WhoisClient.java */ impor ...
- [SSH服务]——一个SSH无密码登陆实验
实验拓扑图 实验描述 机房内有两台服务器: (1)B服务器10.0.10.158,充当Web服务器,有普通用户user_00 (2)C服务器10.0.10.191,充当Mysql服务器,有普通用户us ...
- 邻接表实现Dijkstra算法以及DFS与BFS算法
//============================================================================ // Name : ListDijkstr ...