DD摆磁铁
作者:互联网
现在萨摩耶给了 DDDD 一棵树,树上有 2*m2∗m 个节点上有磁铁, DDDD 要把他们配对成 mm 对,为了让一对中两个磁铁的吸引减少,我们要使 \sum_{i=1}^{m}dis_{pair}∑
i=1
m
dis
pair
最大化
DDDD 想知道距离和最大为多少
输入格式
第一行两个整数分别表示 n,mn,m
第二行 2*m2∗m 个整数,表示哪些点上有磁铁
接下来 n-1n−1 行,每行两个整数表示 u_i,v_iu
i
,v
i
输出格式
一个整数表示最大化的距离和为多少
数据范围
对于 $20% $的数据, \(n \leq 10\)
对于 \(50\%\) 的数据, \(n \leq 1000\)
对于 \(100\%\) 的数据, \(n \leq 200000\)
输出时每行末尾的多余空格,不影响答案正确性
样例输入
7 2
1 2 5 6
1 3
2 3
4 5
3 7
4 3
4 6
样例输出
6
考虑一条边会被计算多少次。在最大的情况下,一条边会被算多少次,要看他的两条边所延伸出的子树有多大。
那么设一条边一端有a个,另一端有b个,那么最大的情况肯定让左右两端都经过这条边,也就加上\(\min(a,b)\)个
在具体的搜索中,设一个点为根,设\(sz_x\)为以x为子树的中有多少个特殊的店,然后\((u,v)\)这条边设\(u\)更接近根,那么答案加上\(\min(2m-sz_v,sz_v)\)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,a[N],sz[N],u,v;
vector<int>g[N];
long long cnt=0;
void sou(int x,int y)
{
for(int i=0;i<g[x].size();i++)
{
if(g[x][i]!=y)
{
sou(g[x][i],x);
sz[x]+=sz[g[x][i]];
cnt+=min(sz[g[x][i]],m+m-sz[g[x][i]]);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m+m;i++)
scanf("%d",a+i),sz[a[i]]=1;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
sou(1,0);
printf("%lld",cnt);
return 0;
}
标签:磁铁,sz,int,DD,整数,leq,DDDD 来源: https://www.cnblogs.com/mekoszc/p/16270325.html