poj 2763 Housewife Wind 【LCA or 树链剖分】
来源:互联网 发布:司法拍卖淘宝网房产 编辑:程序博客网 时间:2024/04/30 14:45
Description
Since Jiajia earned enough money, Wind became a housewife. Their children loved to go to other kids, then make a simple call to Wind: 'Mummy, take me home!'
At different times, the time needed to walk along a road may be different. For example, Wind takes 5 minutes on a road normally, but may take 10 minutes if there is a lovely little dog to play with, or take 3 minutes if there is some unknown strange smell surrounding the road.
Wind loves her children, so she would like to tell her children the exact time she will spend on the roads. Can you help her?
Input
The following n-1 lines each contains three integers a, b and w. That means there is a road directly connecting hut a and b, time required is w. 1<=w<= 10000.
The following q lines each is one of the following two types:
Message A: 0 u
A kid in hut u calls Wind. She should go to hut u from her current position.
Message B: 1 i w
The time required for i-th road is changed to w. Note that the time change will not happen when Wind is on her way. The changed can only happen when Wind is staying somewhere, waiting to take the next kid.
Output
Sample Input
3 3 11 2 12 3 20 21 2 30 3
Sample Output
13
WA8次才过,就因为用错了数组。。。
题意:有N个点和N-1条无向边构成了一棵树。给你起点S和Q次查询,查询分两种:
一,0 a 让你求所在节点到a的最短距离;二,1 a b 把第 a 条边的边权改为b。
思路:用dist[i]存储节点i到root的最短距离,用node[i]记录i节点在DFS树中的深度。
1,求两节点间最短距离——LCA转RMQ算法解决,对于a、b两点距离,有dist[a] + dist[b] - 2 * dist[LCA(a, b)];
2,修改边权的环节——邻接表建边,找到要修改的边很简单。但一条边边权的修改最坏情况下会影响到N-1个点的dist[]值,这样对下面查询两点最短距离造成很大影响,我们要做的是——更新那些受影响的点的dist值。设要修改的边起点为a,终点为b。那我们必须要知道这条边边权的改变影响到哪些点的dist值,显然,树中被影响的节点是——深度大于max(node[a], node[b])的点(并不是所有),知道这点实现更新dist[]就简单了。
过程:
记录修改边起点a和终点b并求出边权变化量change(变化后的 - 变化前的)。然后从max(node[a], node[b])j即深度较大的点向下搜索,在搜索过程中修改dist值 即 dist[] += change。
注意:在我的代码work(u, fa, change)中,u 是起点和终点里深度较大的点,fa则看作是u的父节点(深度比u小),不要弄混淆了。还有起点S要随时更新。
AC代码:
#include <cstdio>#include <cstring>#include <queue>#include <vector>#include <algorithm>#define MAXN 100000+100#define MAXM 400000+100using namespace std;struct Edge{ int from, to, val, next;};Edge edge[MAXM];int head[MAXN], edgenum;int vs[MAXN<<1];int depth[MAXN<<1];int node[MAXN];//记录节点的深度int id[MAXN];int dfs_clock;//时间戳int dist[MAXN];int N, Q, S;//N个点 Q次查询 S起点void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w){ Edge E = {u, v, w, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}void getMap(){ int a, b, c; for(int i = 1; i < N; i++) { scanf("%d%d%d", &a, &b, &c); addEdge(a, b, c), addEdge(b, a, c); }}void DFS(int u, int fa, int d)//遍历整棵树{ node[u] = d;//u节点的深度优先数 id[u] = dfs_clock; vs[dfs_clock] = u; depth[dfs_clock++] = d; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == fa) continue; dist[v] = dist[u] + edge[i].val; DFS(v, u, d+1); vs[dfs_clock] = u; depth[dfs_clock++] = d; }}void find_depth(){ dfs_clock = 1; memset(vs, 0, sizeof(vs)); memset(depth, 0, sizeof(depth)); memset(node, 0, sizeof(node)); memset(id, 0, sizeof(id)); memset(dist, 0, sizeof(dist)); DFS(1, -1, 0);}int dp[MAXN<<1][30];void RMQ_init(int NN)//RMQ预处理区间 最小值{ for(int i = 1; i <= NN; i++) dp[i][0] = i; for(int j = 1; (1<<j) <= NN; j++) { for(int i = 1; i + (1<<j) - 1 <= NN; i++) { int a = dp[i][j-1]; int b = dp[i + (1<<(j-1))][j-1]; if(depth[a] <= depth[b]) dp[i][j] = a; else dp[i][j] = b; } }}int query(int L, int R){ int k = 0; while((1<<(k+1)) <= R-L+1) k++; int a = dp[L][k]; int b = dp[R - (1<<k) + 1][k]; if(depth[a] <= depth[b]) return a; else return b;}int LCA(int u, int v){ int x = id[u]; int y = id[v]; if(x >= y) return vs[query(y, x)]; else return vs[query(x, y)];}void work(int u, int fa, int change){ dist[u] += change; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == fa) continue; work(v, u, change); }}void solve(){ int op, a, b; while(Q--) { scanf("%d", &op); if(op == 0) { scanf("%d", &a); printf("%d\n", dist[S] + dist[a] - 2 * (dist[LCA(S, a)])); S = a;//变换起点 } else { scanf("%d%d", &a, &b);//把第a条边上的权值改为b int k = (a-1)<<1;//边的编号 int change = b - edge[k].val;//改变量 edge[k].val = edge[k^1].val = b;//改变 int a = edge[k].from; int b = edge[k].to;//记录变动边的起点终点 //因为该边权值被改变,深度大于它们的点的dist也要改变 int u = node[a] < node[b] ? a : b; int v = node[a] > node[b] ? a : b; work(v, u, change);//改变 所有被影响的dist值 } }}int main(){ while(scanf("%d%d%d", &N, &Q, &S) != EOF) { init(); getMap(); find_depth(); RMQ_init(dfs_clock - 1); solve(); } return 0;}
树链剖分:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <set>#include <vector>#include <string>#define INF 0x3f3f3f3f#define eps 1e-8#define MAXN (100000+10)#define MAXM (300000+10)#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%.2lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while((a)--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 1000000007#define LL long long#define lson o<<1, l, mid#define rson o<<1|1, mid+1, r#define ll o<<1#define rr o<<1|1#define PI acos(-1.0)#pragma comment(linker, "/STACK:102400000,102400000")#define fi first#define se secondusing namespace std;struct Tree{ int l, r, sum;};Tree tree[MAXN<<2];void PushUp(int o){ tree[o].sum = tree[ll].sum + tree[rr].sum;}void Build(int o, int l, int r){ tree[o].l = l; tree[o].r = r; tree[o].sum = 0; if(l == r) return ; int mid = (l + r) >> 1; Build(lson); Build(rson);}void Update(int o, int pos, int v){ if(tree[o].l == tree[o].r) { tree[o].sum = v; return ; } int mid = (tree[o].l + tree[o].r) >> 1; if(pos <= mid) Update(ll, pos, v); else Update(rr, pos, v); PushUp(o);}int Query(int o, int L, int R){ if(tree[o].l == L && tree[o].r == R) return tree[o].sum; int mid = (tree[o].l + tree[o].r) >> 1; if(R <= mid) return Query(ll, L, R); else if(L > mid) return Query(rr, L, R); else return Query(ll, L, mid) + Query(rr, mid+1, R);}struct Edge{ int from, to, val, next;};Edge edge[MAXN<<1];int head[MAXN], edgenum;void init(){ edgenum = 0; CLR(head, -1);}void addEdge(int u, int v, int w){ Edge E = {u, v, w, head[u]}; edge[edgenum] = E; head[u] = edgenum++;}int son[MAXN], num[MAXN];int top[MAXN], pos[MAXN], id;int dep[MAXN], pre[MAXN];void DFS1(int u, int fa, int d){ dep[u] = d; pre[u] = fa; num[u] = 1; son[u] = -1; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == fa) continue; DFS1(v, u, d+1); num[u] += num[v]; if(son[u] == -1 || num[son[u]] < num[v]) son[u] = v; }}void DFS2(int u, int T){ top[u] = T; pos[u] = ++id; if(son[u] == -1) return ; DFS2(son[u], T); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == pre[u] || v == son[u]) continue; DFS2(v, v); }}int Dist(int u, int v){ int f1 = top[u], f2 = top[v]; int ans = 0; while(f1 != f2) { if(dep[f1] < dep[f2]) { swap(u, v); swap(f1, f2); } ans += Query(1, pos[f1], pos[u]); u = pre[f1], f1 = top[u]; } if(u == v) return ans; if(dep[u] > dep[v]) swap(u, v); ans += Query(1, pos[son[u]], pos[v]); return ans;}int s[MAXN], e[MAXN], c[MAXN];int main(){ int n, S, q; while(scanf("%d%d%d", &n, &q, &S) != EOF) { init(); for(int i = 1; i <= n-1; i++) { Ri(s[i]), Ri(e[i]), Ri(c[i]); addEdge(s[i], e[i], c[i]); addEdge(e[i], s[i], c[i]); } DFS1(1, -1, 1); id = 0; DFS2(1, 1); Build(1, 1, id); for(int i = 1; i <= n-1; i++) { if(dep[s[i]] > dep[e[i]]) swap(s[i], e[i]); Update(1, pos[e[i]], c[i]); } W(q) { int op; Ri(op); int x, y; if(op == 1) { Ri(x); Ri(y); Update(1, pos[e[x]], y); } else { Ri(x); Pi(Dist(S, x)); S = x; } } } return 0;}
- poj 2763 Housewife Wind 【LCA or 树链剖分】
- poj 2763 Housewife Wind 树链剖分+LCA
- 【POJ 2763】Housewife Wind【LCA】
- POJ 2763 Housewife Wind (LCA + 树状数组)
- POJ - 2763 Housewife Wind(LCA+暴力)
- POJ 2763Housewife Wind(LCA)
- POJ 2763 Housewife Wind (LCA+线段树)
- poj 2763 Housewife Wind(树链剖分)
- POJ 2763 Housewife Wind 树链剖分
- POJ 2763 Housewife Wind 树链剖分
- poj 2763 Housewife Wind(树链剖分)
- poj 2763 Housewife Wind 树链剖分
- POJ 2763 Housewife Wind (树链剖分)
- POJ 2763 Housewife Wind 树链剖分
- POJ 2763 Housewife Wind(树链剖分)
- poj 2763 Housewife Wind 树链剖分
- POJ 2763Housewife Wind 树链剖分
- POJ 2763 Housewife Wind (树链剖分)
- Android开发中导入一个项目作为library时出错解决方法
- Palindrome Number
- hdu 3480 dp 四边形不等式优化
- Python-Selenium2做Web自动化测试(1)-软件测试分类以及什么时候需要进行自动化测试
- java并发(一) CountDownLatch (在多个线程都结束后再去执行某个任务)
- poj 2763 Housewife Wind 【LCA or 树链剖分】
- TTS-零基础入门之语音模板化
- 轻松搞定面试中的链表题目
- MyEclipse中new菜单选项问题
- java并发(二) volatile关键字解析
- Fresco一种超强图片加载组件初体验
- return和exit
- 利用Bootstrap制作一个流行的网页
- BZOJ 3884(上帝与集合的正确用法-欧拉函数递推找极限)[Template:数论 V2]