codeforces 700B Connecting Universities 贪心dfs

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

        因为是一棵树,所以一条边把树分成两个集合,假如左边有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+5;
const int INF = 0x3f3f3f3f;
const LL mod = 1ll<<32;
int head[N],tot,sum[N],n,k;
struct Edge{
  int v,next;
}edge[N<<1];
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<<=1;
  memset(head,-1,sizeof(head));
  for(int i=1;i<=k;++i){
     int u;scanf("%d",&u);
     ++sum[u];
  }
  for(int i=1;i<n;++i){
    int u,v;scanf("%d%d",&u,&v);
    add(u,v);add(v,u);
  }
  dfs(1,0);
  printf("%I64d
",ans);
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5701211.html