CF700

你说得太对辣發表於2024-06-29

A.

B.

對每個點分開來計算被經過了多少次,發現只要有兩個點在它的不同側就一定會經過這個點,然後就 dfs 一遍即可。

設一條邊左邊的點的數量為 x,答案即為 \sum \min(x, 2k - x)

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 5e6 + 7;
int p[N];
struct edge {
int next, to;
}e[N];
int head[N], ecnt;
void addedge(int u, int v) {
e[++ ecnt].to = v;
e[ecnt].next = head[u];
head[u] = ecnt;
}
int ans;
int cnt[N];
void dfs(int u, int fa) {
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(v == fa) continue;
dfs(v, u);
cnt[u] += cnt[v];
}
}
signed main() {
memset(head, -1, sizeof head);
int n, k;
cin >> n >> k;
for(int i = 1; i <= 2 * k; i ++) cin >> p[i], cnt[p[i]] = 1;

for(int i = 1; i < n; i ++) {
int u, v;
cin >> u >> v;
addedge(u, v);
addedge(v, u);
}
dfs(1, 0);
int ans = 0;
for(int i = 1; i <= n; i ++) ans += min(cnt[i], 2 * k - cnt[i]);
cout << ans << endl;
}