Codeforces700 B. Connecting Universities(思维,考虑每条边的贡献,cf1800)

题意:

在这里插入图片描述

解法:
题目是求总距离,也就是总边数.
这种题一个技巧是分别考虑每条边的贡献.

对于边(x,v), 设x左侧有L个大学,v右侧有R个大学,那么最优配对下,这条边的贡献就是min(L,R).
因为最优情况下,一定要跨这条边匹配,答案才是最优的.

举个例子:

在这里插入图片描述

对于黑色的边来说,不跨边的匹配方式是:a和b匹配,c和d匹配
这样的匹配方式一定显然不如a和c匹配,b和d匹配。
因为这样的匹配方式,相比于原有的匹配方式,原有的边不变,额外增加了黑色边的贡献。
Code:
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define int long long
#define PI pair<int, int>
const int maxm=3e5+5;
// const int mod=998244353;
const int mod=1e9+7;

int n,k;
int a[maxm];
int sz[maxm];
vector<int>g[maxm];
int ans=0;
void dfs(int x,int fa){
  sz[x]=a[x];
  for(int v:g[x]){
    if(v==fa)continue;
    dfs(v,x);
    ans+=min(k*2-sz[v],sz[v]);
    sz[x]+=sz[v];
  }
}
void solve() {
  cin>>n>>k;
  for(int i=1;i<=k*2;i++){
    int x;cin>>x;
    a[x]=1;
  }
  for(int i=1;i<n;i++){
    int l,r;cin>>l>>r;
    g[l].push_back(r);
    g[r].push_back(l);
  }
  dfs(1,1);
  cout<<ans<<endl;
}
signed main() {
// #define MULTI_CASE
  ios::sync_with_stdio(0);
  cin.tie(0);
#ifndef ONLINE_JUDGE
  freopen("../in.txt", "r", stdin);
  freopen("../out.txt", "w", stdout);
#endif
#ifdef MULTI_CASE
  int T;
  cin >> T;
  while (T--)
#endif
    solve();
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值