题目链接:http://codeforces.com/contest/701/problem/E
题意:有n个城市构成一棵树,一个城市最多有一个学校,这n个城市一共2*k个学校,要对这2*k个学校进行连边,使得所有连出来的边的和最大,每条边边权为1.
题解:这题有一个巧妙的解法,可以记录一下每一条边的贡献(所谓贡献就是有多少对点连线会经过这条边)
也就是记录一下这条边左端点以左的所有需要连的点x和右端点的数目就是2*k-x。然后边的贡献就是两者取
最小。这样dfs一遍所有的边就行了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
const int M = 2e5 + 10;
bool Is[M];
vector<int>vc[M];
ll ans , son[M];
int n , k , x;
void dfs(int pos , int pre) {int len = vc[pos].size();if(Is[pos]) son[pos] = 1;for(int i = 0 ; i < len ; i++) {int v = vc[pos][i];if(v != pre) {dfs(v , pos);son[pos] += son[v];}}ans += min(son[pos] , 2 * k - son[pos]);
}
int main() {scanf("%d%d" , &n , &k);for(int i = 1 ; i <= 2 * k ; i++) {scanf("%d" , &x);Is[x] = true;}int u , v;for(int i = 1 ; i < n ; i++) {scanf("%d%d" , &u , &v);vc[u].push_back(v);vc[v].push_back(u);}ans = 0;memset(son , 0 , sizeof(son));dfs(1 , -1);printf("%I64d\n" , ans);return 0;
}