根据$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. asp.net core使用identity+jwt保护你的webapi(三)——refresh token

    前言 上一篇已经介绍了identity的注册,登录,获取jwt token,本篇来完成refresh token. 开始 开始之前先说明一下为什么需要refresh token. 虽然jwt toke ...

  2. Java(8)详解Random使用

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201556.html 博客主页:https://www.cnblogs.com/testero ...

  3. 轻量级 Java 基础开发框架,Solon & Solon Cloud 1.5.48 发布

    Solon 已有120个生态扩展插件,此次更新主要为细节打磨: 增加 solon.serialization,做为序列化的基础插件 优化 所有Json序列化插件,使之可方便定制类型序列化 public ...

  4. TypeError: module() takes at most 2 arguments (3 given)

    1. 错误提示 2. 代码 class Parent: """定义父类""" def __init__(self): print(" ...

  5. for...in和Object.keys()区别

    区别: for in 用来枚举对象的属性,某些情况下,可能按照随机顺序遍历数组元素 object.keys() 可以返回对象属性为元素的数组,数组中属性名顺序和for in比那里返回顺序一样 ---f ...

  6. JBOSS未授权访问漏洞利用

    1. 环境搭建 https://www.cnblogs.com/chengNo1/p/14297387.html 搭建好vulhub平台后 进入对应漏洞目录 cd vulhub/jboss/CVE-2 ...

  7. [技术博客]大闸蟹的技术博客,通过gitlab api进行用户批量创建

    技术博客--通过gitlab api批量注册用户 gitlab登录界面本身提供了register功能,但需要手工一个个添加,对于一次性会添加整个班级的学生的软工平台来说并不科学合理.使用gitlab ...

  8. OO_JAVA_JML系列第三次作业__架构之谈

    OO_JAVA_JML系列第三次作业 ## ----架构之谈 目录 OO_JAVA_JML系列第三次作业 出发点 操作的可分离性 操作本身的多样性 实现手段:表驱动编程 储存 注册 出发点 操作的可分 ...

  9. jzoj6094

    题目描述 给定一个循环流(每个点均满足流量平衡条件),这个循环流有$n$个点,且每条边的流量只有 $1$ 或$ 2$,其中$a$条边流量为$1$,$b$条边流量为$2$,判断是否存在一个流满足上述条件 ...

  10. Python基础——数据类型——字符串

    整数.浮点数.布尔值的用法大同小异,而Python字符串的一些用法不易记住,这里以廖雪峰教程为基础,进行一些思考和复习总结. 字符串是什么? 以单引号'或者双引号"括起来的任意文本,比如:& ...