Query on a tree
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
题目链接:https://vjudge.net/problem/SPOJ-QTREE
题目大意:t组输入,有n个点,n-1条边,u,v,k是边的两端点和权值,有多条查询:
QUERY u,v 查询u到v的最短路径上的最大边权,CHANGE u,k 改变第u条边的权值为k , DONE 查询结束
思路:这道题和之前的题目不一样的地方在于它是每条边有一个权值,而不是每个点,那就可以把它转变成点带权,可以把每条边的权值赋给下面的那一点,也就是深度较大的那一点,可以发现除了根节点每个节点都对应着一条边的权。其余的就和之前的题差不多
注意:在求一条链上 x点到y点的最大边权的时候查询的应该是区间 [ id[ son[x] ] , id[y] ] ,而不是[ id[x] , id[y] ] 因为 id[x] 带的是它和它的父节点之间的边权,并不在路径上
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int N=10005;
int first[N],n,w[N],tot,cnt,maxx[N<<2];
int d[N],fa[N],siz[N],son[N],top[N],id[N],rk[N];
struct node
{
int u,v,w,nex;
}e[N<<1];
void adde(int u,int v,int w)
{
e[tot].u=u,e[tot].v=v;
e[tot].w=w;
e[tot].nex=first[u];
first[u]=tot++;
}
void init()
{
memset(first,-1,sizeof(first));
memset(son,0,sizeof(son));
tot=cnt=0;
}
void dfs1(int u,int pre,int depth) //处理 d,fa,siz,son 数组
{
d[u]=depth;
fa[u]=pre;
siz[u]=1;
for(int i=first[u];~i;i=e[i].nex)
{
int v=e[i].v;
if(v==pre) continue;
dfs1(v,u,depth+1);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
son[u]=v;
}
}
void dfs2(int u,int t) //处理 top id rk wt 数组
{
top[u]=t;
id[u]=++cnt;
rk[cnt]=u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=first[u];~i;i=e[i].nex)
{
int v=e[i].v;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
void pushup(int rt)
{
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
maxx[rt]=w[l];
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int k,int c,int l,int r,int rt)
{
if(l==r)
{
maxx[rt]=c;
return;
}
int mid=(l+r)>>1;
if(k<=mid) update(k,c,lson);
else update(k,c,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return maxx[rt];
int mid=(l+r)>>1,ans=0;
if(L<=mid) ans=max(ans,query(L,R,lson));
if(R>mid) ans=max(ans,query(L,R,rson));
return ans;
}
int quemax(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(d[top[x]]<d[top[y]]) swap(x,y);
ans=max(ans,query(id[top[x]],id[x],1,n,1));
x=fa[top[x]];
}
if(d[x]>d[y]) swap(x,y);
ans=max(ans,query(id[son[x]],id[y],1,n,1));
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int u,v,k;
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&k);
adde(u,v,k);
adde(v,u,k);
}
dfs1(1,0,1);
dfs2(1,1);
for(int i=0;i<tot;i+=2)
{
if(d[e[i].u]<d[e[i].v]) swap(e[i].u,e[i].v);
w[id[e[i].u]] = e[i].w;
}
build(1,n,1);
char s[10];
while(~scanf("%s",&s))
{
if(s[0]=='D') break;
else if(s[0]=='C')
{
scanf("%d%d",&u,&k);
update(id[e[u*2-2].u],k,1,n,1);
}
else if(s[0]=='Q')
{
scanf("%d%d",&u,&v);
int ans=quemax(u,v);
printf("%d\n",ans);
}
}
}
return 0;
}