SPOJ Problem Set (classical)375. Query on a treeProblem code: QTREE |
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.
We will ask you to perfrom some instructions of the following form:
- CHANGE i ti : change the cost of the i-th edge to ti
or - QUERY a b : ask for the maximum edge cost on the path from node a to node b
Input
The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.
For each test case:
- In the first line there is an integer N (N <= 10000),
- In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
- The next lines contain instructions "CHANGE i ti" or "QUERY a b",
- The end of each test case is signified by the string "DONE".
There is one blank line between successive tests.
Output
For each "QUERY" operation, write one integer representing its result.
Example
Input: 1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE Output: 1 3
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
const int INF = 233333333;
using namespace std;
struct Tree
{
int LC, RC, FA, MAX, KEY;
};
#define lc(x) tree[x].LC
#define rc(x) tree[x].RC
#define fa(x) tree[x].FA
#define Max(x) tree[x].MAX
#define key(x) tree[x].KEY
struct Edge
{
int next, node, v;
};
Tree tree[10010];
Edge e[20010];
int n, m, T;
int h[10010], tot;
int belong[10010];
queue<int> q;
bool vis[10010];
inline void Update(int x)
{
Max(x) = max(max(Max(lc(x)), Max(rc(x))), key(x));
}
inline void set(int x)
{
lc(x) = rc(x) = 0;
}
inline bool isRINFt(int x)
{
return lc(fa(x)) != x && rc(fa(x)) != x;
}
inline void Zig(int x)
{
int y=fa(x), z=fa(y);
if (lc(z)==y) lc(z)=x;
else if (rc(z)==y) rc(z)=x;
fa(x)=z;
fa(rc(x))=y;
lc(y)=rc(x);
fa(y)=x;
rc(x)=y;
Update(y);
}
inline void Zag(int x)
{
int y=fa(x), z=fa(y);
if (lc(z)==y) lc(z)=x;
else if (rc(z)==y) rc(z)=x;
fa(x)=z;
fa(lc(x))=y;
rc(y)=lc(x);
fa(y)=x;
lc(x)=y;
Update(y);
}
inline void Splay(int x)
{
for(int y, z;!isRINFt(x);)
{
y=fa(x);z=fa(y);
if (isRINFt(y))
{
if (lc(y)==x)Zig(x);
else Zag(x);
}
else
{
if (lc(z)==y)
{
if (lc(y)==x)Zig(y), Zig(x);
else Zag(x), Zig(x);
}
else
{
if (rc(y)==x)Zag(y), Zag(x);
else Zig(x), Zag(x);
}
}
}
Update(x);
}
inline void Expose(int x)
{
for(int y=0;x;x=fa(x))
{
Splay(x);
rc(x)=y;
Update(x);
y=x;
}
}
void Build(void)
{
q.push(1);vis[1]=true;
int x, y;set(1);fa(1)=0;
while (!q.empty())
{
x=q.front();q.pop();
for (int i = h[x]; i; i = e[i].next)
{
y=e[i].node;
if (vis[y])continue;
set(y);fa(y)=x;key(y)=e[i].v;belong[i>>1]=y;vis[y]=true;q.push(y);
}
}
}
inline void Modify(int x, int y)
{
key(x)=y;
Splay(x);
}
int Query(int x, int y)
{
Expose(y);
for(y=0;x;x=fa(x))
{
Splay(x);
if (!fa(x)){return max(Max(rc(x)), Max(y));}
rc(x)=y;Update(x);y=x;
}
}
inline void add(int a, int b, int c)
{
e[++tot].next=h[a];
e[tot].node=b;
e[tot].v=c;
h[a]=tot;
}
inline void Work(void)
{
char ch[10];int a, b;
while (1)
{
scanf("%s", ch);
if (ch[0]=='D') return;
scanf("%d%d", &a, &b);
if (ch[0]=='C') Modify(belong[a], b);
else printf("%d\n", Query(a, b));
}
}
int main(void)
{
for(scanf("%d", &T); T; T--)
{
scanf("%d", &n);
int a, b, c;
tot = 1;
for (int i = 0; i <= n; ++i) h[i]=vis[i]=0;
for (int i = 1; i <= n - 1; ++i) scanf("%d%d%d", &a, &b, &c), add(a, b, c), add(b, a, c);
key(0)=Max(0)=-INF;
Build();
Work();
}
return 0;
}
本文介绍了一种解决树形结构中路径最大边权查询及动态更新边权问题的方法。通过使用链剖分(Splay Tree)技术实现高效查询与更新操作。具体包括输入输出格式说明、核心算法思想及实现细节。
857

被折叠的 条评论
为什么被折叠?



