codeforces 700B. Connecting Universities

贪心

题目传送门

题目大意: 一棵树上有 2 k 2k 2k个关键点,把这些关键点两两配对,贡献为配对点的距离之和。求最大贡献。

树上两点之间的距离为 d e p [ x ] + d e p [ y ] − 2 ∗ d e p [ l c a ( x , y ) ] dep[x]+dep[y]-2*dep[lca(x,y)] dep[x]+dep[y]2dep[lca(x,y)]。对于这 2 k 2k 2k个点,它们的深度之和是确定的,那么我们要使尽可能多的lca深度尽量小。

对于一个节点 x x x,设其子树中的关键点个数为 s z [ x ] sz[x] sz[x],其子节点的子树中最多的关键点个数为 m x mx mx,之前已经配对的点个数为 s s s。如果 m x ∗ 2 ≤ s z [ x ] + s mx*2\leq sz[x]+s mx2sz[x]+s,那么对于 x x x子树中所有的关键点,一定存在一种配对方案使得它们的LCA都是 x x x。否则最多会有 ( s z [ x ] − m x ) ∗ 2 (sz[x]-mx)*2 (sz[x]mx)2个关键点被配对(所有点都和 m x mx mx里的点配对), m x mx mx中还剩下 2 ∗ m x − s z [ x ] 2*mx-sz[x] 2mxsz[x]个关键点,这些要累加到 s s s中并递归子树 m x mx mx

s = 2 k − s z [ x ] s=2k-sz[x] s=2ksz[x],把上述化简即若 m x ≤ k mx\leq k mxk则贡献为 2 d e p [ x ] ∗ ( s z [ x ] − k ) 2dep[x]*(sz[x]-k) 2dep[x](sz[x]k),否则为 2 d e p [ x ] ∗ ( s z [ x ] − m x ) 2dep[x]*(sz[x]-mx) 2dep[x](sz[x]mx)。DFS算一遍就好了。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200005
#define F inline
using namespace std;
typedef long long LL;
struct edge{ int nxt,to; }ed[N<<1];
int n,m,k,a[N],h[N],sz[N],fa[N],dep[N];
bool f[N]; LL ans;
F char readc(){
	static char buf[100000],*l=buf,*r=buf;
	if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
	return l==r?EOF:*l++;
}
F int _read(){
	int x=0; char ch=readc();
	while (!isdigit(ch)) ch=readc();
	while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
	return x;
}
void dfs1(int x){
	dep[x]=dep[fa[x]]+1,sz[x]=f[x];
	for (int i=h[x],v;i;i=ed[i].nxt)
		if ((v=ed[i].to)!=fa[x]) fa[v]=x,dfs1(v),sz[x]+=sz[v];
}
void dfs2(int x){
	int mx=0,id;
	for (int i=h[x],v;i;i=ed[i].nxt)
		if ((v=ed[i].to)!=fa[x]&&mx<sz[v]) mx=sz[v],id=v;
	if (mx<<1<=sz[1])
		return void(ans-=1ll*dep[x]*(2*sz[x]-sz[1]));
	ans-=1ll*(sz[x]-mx)*dep[x]<<1,dfs2(id);
}
#define add(x,y) ed[++k]=(edge){h[x],y},h[x]=k
int main(){
	n=_read(),m=_read()<<1;
	for (int i=1;i<=m;i++) f[a[i]=_read()]=true;
	for (int i=1,x,y;i<n;i++)
		x=_read(),y=_read(),add(x,y),add(y,x);
	dfs1(1),dfs2(1);
	for (int i=1;i<=m;i++) ans+=dep[a[i]];
	return printf("%lld",ans),0;
}
您提供的链接是Codeforces的一个问题,问题编号为104377。Codeforces是一个知名的在线编程竞赛平台,经常举办各种编程比赛和训练。Gym是Codeforces的一个扩展包,用于组织私人比赛和训练。您提供的链接指向了一个问题的页面,但具体的问题内容和描述无法通过链接获取。如果您有具体的问题或需要了解关于Codeforces Gym的更多信息,请提供更详细的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [http://codeforces.com/gym/100623/attachments E题](https://blog.csdn.net/weixin_30820077/article/details/99723867)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [http://codeforces.com/gym/100623/attachments H题](https://blog.csdn.net/weixin_38166726/article/details/99723856)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CodeforcesPP:Codeforces扩展包](https://download.csdn.net/download/weixin_42101164/18409501)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值