codeforces 102862H
H. Optimize DFS
time limit per test3 seconds
memory limit per test256 megabytes
You are given a tree with 𝑛 vertices. Every vertex 𝑣 has two values 𝑎𝑣 and 𝑏𝑣. You have to process 𝑞 queries of types:
Given 𝑣 and 𝑥, assign 𝑎𝑣=𝑥;
Given 𝑣, print 𝑎𝑣;
Given 𝑣, implement the following procedure efficiently:
First, create an array used[1…𝑛] filled with false initially. Then run the function DFS(𝑣):
DFS(v):
{
used[v] = true;
for u from 1 to n do
{
if (u and v are connected by an edge)
and (used[u] == false)
and (a[v] + b[u] == a[u] + b[v]) then
{
DFS(u);
}
}
a[v] = b[v];
}
Note that the array used is independent for each query of the 3rd type.
Input
The first line contains two integers 1≤𝑛,𝑞≤5⋅105. The second line contains 𝑛 integers, where the 𝑖-th is the initial value of 𝑎𝑖 (0≤𝑎𝑖≤5⋅105). The third line contains 𝑛 integers, where the 𝑖-th is the value of 𝑏𝑖 (0≤𝑏𝑖≤5⋅105).
Each of the next 𝑛−1 lines describes an edge of the tree. The 𝑖-th line contains two integers 𝑢𝑖 and 𝑣𝑖 (1≤𝑢𝑖,𝑣𝑖≤𝑛, 𝑢𝑖≠𝑣𝑖), the indices of the vertices connected by the 𝑖-th edge. It is guaranteed that the given graph is a tree.
The next 𝑞 lines contain the description of the queries. The 𝑖-th query starts with an integer 𝑡𝑖 (1≤𝑡𝑖≤3) that denotes the type of the query. If 𝑡𝑖=1, then two integers 𝑣𝑖 and 𝑥𝑖 follow (1≤𝑣𝑖≤𝑛, 0≤𝑥𝑖≤5⋅105). Otherwise only 𝑣𝑖 is given.
Output
For each query of the 2nd type output one integer, the value 𝑎𝑣.
题目要求我们按照树的构造进行多次操作,
三次操作分别是1.替换a[v]=x;
2.查询a[x]当前值
3.进行特殊的dfs,交换特定的值
其中包含了特殊的dfs
关键代码如下
点击查看代码
void dfs(int v){
used[v] = 1;
for (Edge* e = graph[v]; e != NULL; e = e->next){
int u = e->to;
if(!used[u] && a[v] + b[u] == a[u] + b[v]){
dfs(u);
}
}
a[v] = b[v];
}
完整代码如下
点击查看代码
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100005
typedef struct Edge{
int to;
struct Edge* next;
} Edge;
Edge* graph[MAXN]; // 每个节点的邻接链表头指针
int used[MAXN];
int a[MAXN], b[MAXN];
//头插法建树
void add_edge(int u, int v){
Edge* e = (Edge*)malloc(sizeof(Edge));
e->to = v;
e->next = graph[u];
graph[u] = e;
}
void dfs(int v){
used[v] = 1;
for (Edge* e = graph[v]; e != NULL; e = e->next){
int u = e->to;
if(!used[u] && a[v] + b[u] == a[u] + b[v]){
dfs(u);
}
}
a[v] = b[v];
}
int main(){
int n,p;
scanf("%d%d",&n, &p);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++){
scanf("%d", &b[i]);
}
//建树
for (int i = 1; i < n; i++){
int u, v;
scanf("%d %d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
while(p--){
int q;
scanf("%d",&q);
if(q == 1){
int v,x;
scanf("%d%d",&v, &x);
a[v] = x;
}else if(q == 2){
int v;
scanf("%d",&v);
printf("%d\n",a[v]);
}else if(q == 3){
int v;
scanf("%d", &v);
// 一开始树的元素都没有被访问
for (int i = 1; i <= n; i++) {
used[i] = 0;
}
dfs(v);
}
}
return 0;
}

浙公网安备 33010602011771号