根据$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. 每日总结:Java课堂测试第三阶段第二次优化 (四则运算) (2021.9.22)

    package jisuan2; import java.util.*;import java.util.Scanner; public class xiaoxue { public static v ...

  2. 洛谷3703 SDOI2017树点涂色(LCT+线段树+dfs序)

    又一道好题啊qwqqqq 一开始看这个题,还以为是一个树剖的什么毒瘤题目 (不过的确貌似可以用树剖啊) qwq这真是一道\(LCT\)维护颜色的好题 首先,我们来一个一个操作的考虑. 对于操作\(1\ ...

  3. Visual Studio 安装 C++

    Visual Studio 安装 C++

  4. javascript-原生-闭包

    1.变量的作用域 前提:这里只全部都通过var创建的变量或对象 1.全局变量:函数外创建变量 var x=10; function test(){ alert("全局变量在test函数中&q ...

  5. 如何配置log4Net

    之前曾经用过几次,但是每次都是用完就忘了,下次再用的时候要baidu半天,这次弄通之后直接记下来. 步骤如下. 1. 安装log4Net,直接用NuGet, Install-Package log4N ...

  6. kafka-eagle监控界面搭建

    kafka-eagle监控界面搭建 一.背景 二 .mac上安装kafka-eagle 1.安装JDK 2.安装eagle 1.下载eagle 2.解压并配置环境变量 3.启用kafka的JMX 4. ...

  7. elf文件--基于《ctf竞赛权威指南pwn篇》

    1.ELF概念: ELF(Executable and Linkable Format),即"可执行可链接格式",最初由UNIX系统实验室作为应用程序二进制接口(Applicati ...

  8. HDMI之TMDS通道

    HDMI标准继续沿用了和DVI相同的,由Silicon Image公司发明的TMDS(Time Minimized Differential Signal)最小化传输差分信号传输技术.TMDS是一种微 ...

  9. STM32学习笔记之核心板PCB设计

    PCB设计流程 PCB规则设置 设计规则的单位跟随画布属性里设置的单位,此处单位是mil.导线线宽最小为10mil;不同网络元素之间最小间距为8mil;孔外径为24mil,孔内径为12mil;线长不做 ...

  10. 基于Vue的工作流项目模块中,使用动态组件的方式统一呈现不同表单数据的处理方式

    在基于Vue的工作流项目模块中,我们在查看表单明细的时候,需要包含公用表单信息,特定表单信息两部分内容.前者表单数据可以统一呈现,而后者则是不同业务的表单数据不同.为了实现更好的维护性,把它们分开作为 ...