주제 링크 : 포인트 I 아 ╭ (╯ ^ ╰) ╮
효과에 따라 :
뿌리 나무, 무게 및 경로의 수를 찾을
경로는 다음과 같이 정의의 무게 :
최단 경로의 시작부터 끝까지, 모서리의 수는 올라가
모서리의 수는 아래로 이동
문제 해결 아이디어 :
하나 개의 경로에 대한
의 길이를 설정
,
행
거리
, 설정
방향
방향의 아들
용
이 부분, 우측이 경로상의 모든 점에 상당
의 경우
이 섹션도의 차이에 의해 처리 할 수 있습니다
포인트
의
있다
아버지가,
,이어서
즉, 사상의 연산 처리 순서의 차이는
코어 : 연산 처리 순서를 트리 차이점
#include<bits/stdc++.h>
#define rint register int
#define x first
#define y second
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <ll,ll>;
const int maxn = 3e5 + 5;
int n, m, f[maxn][35];
ll ans[maxn], dep[maxn];
vector <int> g[maxn];
pii a[maxn];
void dfs1(int u, int fa, int de) {
dep[u] = de, f[u][0] = fa;
for(int i=1; i<=30; i++)
f[u][i] = f[f[u][i-1]][i-1];
for(auto v : g[u]) {
if(v == fa) continue;
dfs1(v, u, de+1);
}
}
int LCA(int x, int y){
if(dep[x]<dep[y]) swap(x, y);
for(int i=30; i>=0; i--)
if(dep[f[x][i]]>=dep[y])
x = f[x][i];
if(x == y) return x;
for(int i=30; i>=0; i--)
if(f[x][i] ^ f[y][i])
x=f[x][i], y=f[y][i];
return f[x][0];
}
void dfs2(int u, int fa) {
for(auto v : g[u]) {
if(v == fa) continue;
dfs2(v, u);
a[u].x += a[v].x;
a[u].y += a[v].y;
}
a[u].x -= 2ll * a[u].y;
}
void dfs3(int u, int fa, ll num) {
ans[u] = num;
for(auto v : g[u]) {
if(v == fa) continue;
dfs3(v, u, num - a[v].x);
}
}
int main() {
scanf("%d%d", &n, &m);
for(int i=1, u, v; i<n; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1, 0, 1);
while(m--) {
ll u, v, lca, len;
scanf("%lld%lld", &u, &v);
lca = LCA(u, v);
len = dep[u] + dep[v] - 2ll * dep[lca];
a[u].x += len + 1, a[u].y += 1;
a[lca].x -= len + 1 - 2ll * (dep[u] - dep[lca]), a[lca].y -= 1;
a[v].x += len + 1, a[v].y += 1;
a[lca].x -= len + 1 - 2ll * (dep[v] - dep[lca]), a[lca].y -= 1;
ans[1] += 1ll * (dep[u] - dep[lca]) * (dep[v] - dep[lca]);
}
dfs2(1, 0);
dfs3(1, 0, ans[1]);
for(int i=1; i<=n; i++) printf("%lld\n", ans[i]);
}