codeforces 702B

题意:给出n个城镇,k对学校,k对学校分布在不同的城镇,然后给出2*k个学校所在城镇的编号,然后再给出n-1条边连接的两个城镇,保证每一个城镇都能到达任何一个其他城镇,2*k个学校可以任意配对,要求每一队配对的学校的距离总和最大,每一条边的距离是1

思路:如果对于一个点而言,如果这些学校分布在这个点的左子树和右子树,那么我们可以求出这些学校到这个点的距离然后加起来就是结果,但是题目并不保证这个条件,这时我们可以算每一条边对答案的贡献,对一条边而言,左边如果有a个学校,右边肯定是2*k-a个学校,那么肯定少的那一边要连到多的那一边去,那么答案就是min(a, 2*k-a),这个就直接在树上求结果就行了, 这题答案要用long long 来存,

#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int qq = 200000+10;
vector<int>v[qq];
ll dp[qq]={0};
int vis[qq]={0};
ll ans = 0;
ll n,k;
void dfs(int rt, int fa){
	if(vis[rt]) dp[rt] = 1;
	for(int i=0; i<v[rt].size(); ++i){
		int to = v[rt][i];
		if(to==fa)	continue;
		dfs(to, rt);
		dp[rt]+=dp[to];
		ans+=min(dp[to], 2*k-dp[to]);
	}
}
int main(){
	scanf("%lld%lld",&n, &k);
	int x;
	for(int i=1; i<=2*k; ++i){
		scanf("%d",&x);
		vis[x]++;
	}
	for(int i=1; i<n; ++i){
		int a,b;
		scanf("%d%d",&a, &b);
		v[a].push_back(b);
		v[b].push_back(a);
	}
	dfs(1, -1);
	printf("%lld\n", ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值