codeforces 700B Connecting Universities 贪心dfs

时间:2024-01-15 18:47:44

分析:这个题一眼看上去很难,但是正着做不行,我们换个角度:考虑每条边的贡献

因为是一棵树,所以一条边把树分成两个集合,假如左边有x个学校,右边有y个学校

贪心地想,让每条边在学校的路径上最多,所以贡献为min(x,y)

具体实现:一次dfs即可,复杂度O(N)

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <stack>
#include <map>
using namespace std;
typedef long long LL;
const int N = 2e5+;
const int INF = 0x3f3f3f3f;
const LL mod = 1ll<<;
int head[N],tot,sum[N],n,k;
struct Edge{
int v,next;
}edge[N<<];
void add(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
LL ans;
void dfs(int u,int f){
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(v==f)continue;
dfs(v,u);
ans+=min(k-sum[v],sum[v]);
sum[u]+=sum[v];
}
}
int main(){
scanf("%d%d",&n,&k);k<<=;
memset(head,-,sizeof(head));
for(int i=;i<=k;++i){
int u;scanf("%d",&u);
++sum[u];
}
for(int i=;i<n;++i){
int u,v;scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(,);
printf("%I64d\n",ans);
return ;
}