[cf1396E]Distance Matching
根据$dis(x,y)=d[x]+d[y]-2d[lca(x,y)]$,由于所有点都出现了1次,距离即$\sum_{i=1}^{n}d_{i}-2\sum d[lca(x,y)]$(以下假设根深度为0)
构造:以重心$r$为根,选择$r$的所有儿子中子树大小最大的两个,从这两颗子树中各选一个点匹配并删除,利用重心性质可以使得所有$d[lca(x,y)]=0$,即得到答案最大值$\sum_{i=1}^{n}d_{i}$(距离与根无关)
答案要求为$k$,令$k'=\frac{\sum_{i=1}^{n}d_{i}-k}{2}$(若无法整除2则显然无解),我们要让所有$d[lca(x,y)]$之和为$k'$
构造:选择$r$的所有儿子中最大的1个,若$k'\ge d-1$($d$为该子树深度),则从中选出2个点使得lca深度为$d-1$(选择最深的点和其兄弟,若没有兄弟改为和其父亲),之后$k'-=d-1$,否则找到深度为$k'$且不为叶子的点(必然存在,因为整颗树深度为$d$),将其与其儿子匹配即可
具体实现中,对每颗子树需要支持:1.删除一个点;2.查询某深度的点,用set维护,同时外部还需要用优先队列来维护子树大小,时间复杂度都是$o(n\log_{2}n)$,常数可能稍大

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 struct ji{
5 int nex,to;
6 }edge[N<<1];
7 set<pair<int,int> >s[N];
8 set<pair<int,int> >::iterator it;
9 priority_queue<pair<int,int> >q;
10 pair<int,int>ans[N];
11 int E,n,r,x,y,z,cnt,head[N],sz[N],mx[N],f[N],d[N];
12 long long m;
13 void add(int x,int y){
14 edge[E].nex=head[x];
15 edge[E].to=y;
16 head[x]=E++;
17 }
18 void dfs(int k,int fa){
19 sz[k]=1;
20 mx[k]=0;
21 for(int i=head[k];i!=-1;i=edge[i].nex)
22 if (edge[i].to!=fa){
23 dfs(edge[i].to,k);
24 sz[k]+=sz[edge[i].to];
25 mx[k]=max(mx[k],sz[edge[i].to]);
26 }
27 if (max(n-sz[k],mx[k])<=n/2)r=k;
28 }
29 void dfs(int k,int fa,int sh){
30 f[k]=fa;
31 d[k]=sh;
32 m-=sh;
33 s[x].insert(make_pair(sh,k));
34 sz[k]=1;
35 for(int i=head[k];i!=-1;i=edge[i].nex)
36 if (edge[i].to!=fa){
37 dfs(edge[i].to,k,sh+1);
38 sz[k]+=sz[edge[i].to];
39 }
40 }
41 int main(){
42 scanf("%d%lld",&n,&m);
43 memset(head,-1,sizeof(head));
44 for(int i=1;i<n;i++){
45 scanf("%d%d",&x,&y);
46 add(x,y);
47 add(y,x);
48 }
49 dfs(1,0);
50 for(int i=head[r];i!=-1;i=edge[i].nex){
51 x=edge[i].to;
52 dfs(x,r,1);
53 q.push(make_pair(sz[x],x));
54 }
55 if ((m>0)||(m%2)){
56 printf("NO");
57 return 0;
58 }
59 m/=-2;
60 while (m){
61 x=q.top().second;
62 q.pop();
63 if (sz[x]<2){
64 printf("NO");
65 return 0;
66 }
67 sz[x]-=2;
68 if (sz[x])q.push(make_pair(sz[x],x));
69 if ((*--s[x].end()).first-1<=m){
70 y=(*--s[x].end()).second;
71 s[x].erase(--s[x].end());
72 m-=d[y]-1;
73 z=f[y];
74 bool flag=0;
75 for(int i=head[z];i!=-1;i=edge[i].nex)
76 if ((edge[i].to!=f[z])&&(edge[i].to!=y)&&(s[x].find(make_pair(d[edge[i].to],edge[i].to))!=s[x].end())){
77 ans[++cnt]=make_pair(edge[i].to,y);
78 s[x].erase(make_pair(d[edge[i].to],edge[i].to));
79 flag=1;
80 break;
81 }
82 if (!flag){
83 ans[++cnt]=make_pair(z,y);
84 s[x].erase(make_pair(d[z],z));
85 }
86 }
87 else{
88 it=lower_bound(s[x].begin(),s[x].end(),make_pair((int)m,0));
89 while ((*it).first==m){
90 bool flag=0;
91 y=(*it).second;
92 for(int i=head[y];i!=-1;i=edge[i].nex)
93 if ((edge[i].to!=f[y])&&(s[x].find(make_pair(d[edge[i].to],edge[i].to))!=s[x].end())){
94 ans[++cnt]=make_pair(y,edge[i].to);
95 s[x].erase(make_pair(d[y],y));
96 s[x].erase(make_pair(d[edge[i].to],edge[i].to));
97 flag=1;
98 break;
99 }
100 if (flag)break;
101 it++;
102 }
103 m=0;
104 }
105 }
106 while (!q.empty()){
107 x=q.top().second;
108 q.pop();
109 if (q.empty()){
110 ans[++cnt]=make_pair((*s[x].begin()).second,r);
111 break;
112 }
113 y=q.top().second;
114 q.pop();
115 if (sz[x]>1)q.push(make_pair(--sz[x],x));
116 if (sz[y]>1)q.push(make_pair(--sz[y],y));
117 ans[++cnt]=make_pair((*s[x].begin()).second,(*s[y].begin()).second);
118 s[x].erase(s[x].begin());
119 s[y].erase(s[y].begin());
120 }
121 printf("YES\n");
122 for(int i=1;i<=cnt;i++)printf("%d %d\n",ans[i].first,ans[i].second);
123 }
[cf1396E]Distance Matching的更多相关文章
- CF1396E——Distance Matching
传送门:QAQQAQ(题面翻译) 以后博客可能一直咕咕咕了.一些做题的思考可能会直接放在代码里而不是单独写博客,因为这样太浪费时间,只有一些比较新的题才会单独写博客 思路:对于这种构造可行解使得权值和 ...
- [atARC087F]Squirrel Migration
对这棵树重心情况分类讨论: 1.若这棵树存在两个重心,分别记作$x$和$y$,如果将$(x,y)$断开,两棵子树大小都相同(都为$\frac{n}{2}$),此时$p_{i}$与$i$必然不同属于一个 ...
- world.construct(me);
目录 0 引言 0.1 所谓构造题 0.2 重点是动机 (motivation) 1 实践出真知 1.1 「CSP-S 2021」「洛谷 P7915」回文 1.1.1 题目大意 1.1.2 解题过程 ...
- 最喜欢的算法(们) - Levenshtein distance
String Matching: Levenshtein distance Purpose: to use as little effort to convert one string into th ...
- Scipy教程 - 距离计算库scipy.spatial.distance
http://blog.csdn.net/pipisorry/article/details/48814183 在scipy.spatial中最重要的模块应该就是距离计算模块distance了. fr ...
- Direct Shot Correspondence Matching
一篇BMVC18的论文,关于semantic keypoints matching.dense matching的工作,感觉比纯patch matching有意思,记录一下. 1. 摘要 提出一种针对 ...
- Matching Networks for One Shot Learning
1. Introduction In this work, inspired by metric learning based on deep neural features and memory a ...
- Hausdorff Distance(豪斯多夫距离)
Hausdorff Distance(豪斯多夫距离) 参考博客:http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/98/normand/ma ...
- Minimum edit distance(levenshtein distance)(最小编辑距离)初探
最小编辑距离的定义:编辑距离(Edit Distance),又称Levenshtein距离.是指两个字串之间,由一个转成还有一个所需的最少编辑操作次数.许可的编辑操作包含将一个字符替换成还有一个字符. ...
随机推荐
- golang []byte和string的高性能转换
golang []byte和string的高性能转换 在fasthttp的最佳实践中有这么一句话: Avoid conversion between []byte and string, since ...
- pycharm中安装和使用sqlite过程详解
创建Django项目,添加app 使用虚拟环境 项目创建默认使用的Django数据库是sqlite 配置静态文件 STATIC_URL = '/static/' # HTML中使用的静态文件夹前缀 S ...
- k8s replicaset controller分析(1)-初始化与启动分析
replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...
- try-catch-finally面试题
try catch finally 执行顺序面试题总结 执行顺序 今天牛客网遇到这个题目,做对了,但是下面的评论却很值得看看 public class TestTry { public int add ...
- Java多线程中的死锁
Java多线程中的死锁 死锁产生的原因 线程死锁是指由两个以上的线程互相持有对方所需要的资源,导致线程处于等待状态,无法往前执行. 当线程进入对象的synchronized代码块时,便占有了资源,直到 ...
- [敏捷软工团队博客]Beta阶段项目展示
团队成员简介和个人博客地址 头像 姓名 博客园名称 自我介绍 PM 测试 前端 后端 dzx 秃头院的大闸蟹 大闸蟹是1706菜市场里无菜可卖的底层水货.大闸蟹喜欢音乐(但可惜不会),喜欢lol(可惜 ...
- OO_JAVA_JML系列作业_单元总结
OO_JAVA_JML系列作业_单元总结 (1)梳理JML语言的理论基础.应用工具链情况 简单梳理 以下三者是jml规格里的核心,对一个方法功能和属性的限制: requires子句:规定方法的前置条件 ...
- BUAA 2020 软件工程 热身作业
BUAA 2020 软件工程 热身作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! ...
- 修炼Servlet
修炼Servlet 一.Servlet简单认识 1.Servlet是什么 Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的 ...
- Android 服务名称规则invalid service name 限制16字符以内
今天调试网络服务的时候为了区分,修改了原有服务名称,同时新增了两个服务. 系统运行的时候报错找不到对应的服务 init: no such service 'wpa_supplicant_common' ...