根据$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的更多相关文章

  1. CF1396E——Distance Matching

    传送门:QAQQAQ(题面翻译) 以后博客可能一直咕咕咕了.一些做题的思考可能会直接放在代码里而不是单独写博客,因为这样太浪费时间,只有一些比较新的题才会单独写博客 思路:对于这种构造可行解使得权值和 ...

  2. [atARC087F]Squirrel Migration

    对这棵树重心情况分类讨论: 1.若这棵树存在两个重心,分别记作$x$和$y$,如果将$(x,y)$断开,两棵子树大小都相同(都为$\frac{n}{2}$),此时$p_{i}$与$i$必然不同属于一个 ...

  3. world.construct(me);

    目录 0 引言 0.1 所谓构造题 0.2 重点是动机 (motivation) 1 实践出真知 1.1 「CSP-S 2021」「洛谷 P7915」回文 1.1.1 题目大意 1.1.2 解题过程 ...

  4. 最喜欢的算法(们) - Levenshtein distance

    String Matching: Levenshtein distance Purpose: to use as little effort to convert one string into th ...

  5. Scipy教程 - 距离计算库scipy.spatial.distance

    http://blog.csdn.net/pipisorry/article/details/48814183 在scipy.spatial中最重要的模块应该就是距离计算模块distance了. fr ...

  6. Direct Shot Correspondence Matching

    一篇BMVC18的论文,关于semantic keypoints matching.dense matching的工作,感觉比纯patch matching有意思,记录一下. 1. 摘要 提出一种针对 ...

  7. Matching Networks for One Shot Learning

    1. Introduction In this work, inspired by metric learning based on deep neural features and memory a ...

  8. Hausdorff Distance(豪斯多夫距离)

    Hausdorff Distance(豪斯多夫距离) 参考博客:http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/98/normand/ma ...

  9. Minimum edit distance(levenshtein distance)(最小编辑距离)初探

    最小编辑距离的定义:编辑距离(Edit Distance),又称Levenshtein距离.是指两个字串之间,由一个转成还有一个所需的最少编辑操作次数.许可的编辑操作包含将一个字符替换成还有一个字符. ...

随机推荐

  1. Miller-Rabin and Pollard-Rho

    实话实说,我自学(肝)了两天才学会这两个随机算法 记录: Miller-Rabin 她是一个素数判定的算法. 首先需要知道费马小定理 \[a^{p-1}\equiv1\pmod{p}\quad p\i ...

  2. 【UE4 C++】 SaveGame 存档/读档

    创建 SaveGame 类 继承自 USaveGame UCLASS() class TIPS_API USimpleSaveGame : public USaveGame { GENERATED_B ...

  3. win10安装git fatal: open /dev/null or dup failed: No such file or directory错误解决方法

    原因看大家意思应该是 非即插即用驱动文件null.sys问题. 网上有很多方案.最后试了一个可行的. 替换  windows/system32/drivers/null.sys为网盘中的文件即可. 链 ...

  4. Scrum Meeting 14

    第14次例会报告 日期:2021年06月07日 会议主要内容概述: 汇报了已完成的工作,明确了下一步目标,正在努力赶进度. 一.进度情况 我们采用日报的形式记录每个人的具体进度,链接Home · Wi ...

  5. [no_code][Beta]项目展示博客

    $( "#cnblogs_post_body" ).catalog() 团队项目链接 Beta阶段核心开发点: github 前端 github 后端 github OCR文档-含 ...

  6. [no code][scrum meeting] Alpha 11

    项目 内容 会议时间 2020-04-17 会议主题 OCR紧急技术风险分析 会议时长 30min 参会人员 PM+OCR组成员 $( "#cnblogs_post_body" ) ...

  7. seata代码控制回滚和临时挂起分布式事物

    seata代码控制回滚和临时挂起分布式事物 一.说明 二.功能实现 1.手动回滚分布式事物 2.临时挂起分布式事物 三.完整代码 四 参考链接 一.说明 此处只是简单的记录一下,使用了 Seata后, ...

  8. Shell脚本学习笔记之(自动填充函数模板)

    其实,vii 就是写的一个脚本,跟 vi 没半毛钱关系,只不过借用一下这个名字而已.那这个脚本长什么样呢?look: 下面来详细的解析上面的代码,来看第1行: #!/bin/bash 这是Shell脚 ...

  9. 一文带你掌握【TCP拥塞窗口】原理

    ❝ 关注公众号:高性能架构探索.后台回复[资料],可以免费领取 ❞ 学过网络相关课程的,都知道TCP中,有两个窗口: 滑动窗口(在我们的上一篇文章中有讲),接收方通过通告发送方自己的可以接受缓冲区大小 ...

  10. 实验7:基于REST API的SDN北向应用实践

    一.实验目的 1.能够编写程序调用OpenDaylight REST API实现特定网络功能: 2.能够编写程序调用Ryu REST API实现特定网络功能. 二.实验环境 下载虚拟机软件Oracle ...