题意:
给定一颗树,每条边连接a和b,每一条边可能有两种操作:
1.以a为起点并且不经过b的所有点权值+x
2.以b为起点并且不经过a的所有点权值+x
思路:从1号点开始BFS,dep【1】=1,给每个点标记好深度。
假设起点为a,不能经过的点为b,如果dep【a】< dep【b】 ,那么val【1】+=x,val【b】-=x;
如果dep【a】> dep[b],直接val【a】+=x。
最后再跑一遍BFS,将val值依次传递就ok了。
树上差分还是第一次见,牛啊
#include <iostream>
#include <cmath>
#include <set>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <queue>
#include <vector>
using namespace std;
#define IO \
ios::sync_with_stdio(false); \
// cin.tie(0); \
// cout.tie(0);
typedef long long LL;
const int maxn = 2e5 + 10;
struct Edge
{
int x, y;
} e[maxn];
vector<int> g[maxn];
LL val[maxn];
int dep[maxn];
int n, q;
void BFS()
{
queue<int> q;
q.push(1);
dep[1] = 1;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if (dep[v] == -1)
{
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return;
}
int main()
{
IO;
int a, b, c;
memset(dep, -1, sizeof dep);
cin >> n;
for (int i = 1; i <= n - 1; i++)
{
cin >> e[i].x >> e[i].y;
g[e[i].x].push_back(e[i].y);
g[e[i].y].push_back(e[i].x);
}
BFS();
cin >> q;
while (q--)
{
cin >> a >> b >> c;
int x = e[b].x;
int y = e[b].y;
if (dep[x] < dep[y])
{
if (a == 1)
val[1] += c, val[y] -= c;
else
val[y] += c;
}
else
{
if (a == 1)
val[x] += c;
else
val[1] += c, val[x] -= c;
}
}
queue<int> q;
q.push(1);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if (dep[v] > dep[u])
{
val[v] += val[u];
q.push(v);
}
}
}
for (int i = 1; i <= n; i++)
cout << val[i] << "\n";
return 0;
}