题目大意:n个点的树,有m*2个点有磁铁,如果配对使得m对磁铁之间的距离之和最大?

对于每一条边,左边有x个磁铁,右边有y个磁铁,要想距离大,那么尽量左右两边互相配对,最多可以配min(x, y)对。每条边都是如此。

#include <bits/stdc++.h>
#define N 200005
using namespace std;
int n, m, i, j, k, a, b, ans, s[N], h[N];
struct AB{
    int a, b, n;
} d[N*2];
void cun(int a, int b){
    d[++k].a = a, d[k].b = b;
    d[k].n = h[a], h[a] = k;
}
void dfs(int a, int p){
    int b, i;
    for(i=h[a]; i; i=d[i].n){
        b = d[i].b;
        if(b != p){
            dfs(b, a);
            s[a] += s[b];
            ans += min(s[b], m*2-s[b]);
        }
    }
}
int main(){
    scanf("%d%d", &n, &m);
    for(i=1; i<=m*2; i++){
        scanf("%d", &j);
        s[j] = 1;
    }
    for(i=1; i<n; i++){
        scanf("%d%d", &a, &b);
        cun(a, b);
        cun(b, a);
    }
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}