CF 700B Connecting Universities

来源:互联网 发布:千牛在哪打开淘宝首页 编辑:程序博客网 时间:2024/04/29 17:43

Description

给出n个点的树,及2*k个节点,给他们每两个进行分组,我们定义一组的贡献为该组的两个节点之间的距离。求这k组的最大的贡献和为多少。

Data Constraint

2 ≤ n ≤ 200 000, 1 ≤ k ≤ n / 2

Solution

我们发现对于一条边,当它左边有要求配对x个节点,右边有要求配对y个节点,那么显然最大的方案就是min(x,y)。所以,我们照着这样对每条边判断一下就好。时间复杂度O(N)。

代码

#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const int maxn=400005;ll first[maxn],last[maxn],next[maxn],num,n,i,t,j,k,l,size[maxn],m,x,y,ans;bool bz[maxn];void lian(int x,int y){    last[++num]=y;next[num]=first[x];first[x]=num;}void dg(ll x,ll y){    ll t;    for (t=first[x];t;t=next[t]){        if (last[t]==y) continue;        dg(last[t],x);        size[x]+=size[last[t]];        ans+=min(size[last[t]],2*m-size[last[t]]);    }    if (bz[x]) size[x]++;}int main(){    //freopen("data.in","r",stdin);    scanf("%d%d",&n,&m);    for (i=1;i<=2*m;i++)        scanf("%d",&x),bz[x]=true;    for (i=1;i<n;i++)        scanf("%d%d",&x,&y),lian(x,y),lian(y,x);    dg(1,0);    printf("%lld\n",ans);}
3 0