题目描述:

由于 zzq 太懒了,所以这题没有题目背景。

有一棵树,树上有 n 个点,每条边上有一个非负边权。

在这 n 个点中有 k 个特殊点,其中 k 为偶数。定义两个点的距离为它们在树上的简单路径上的边权之和。你需要将这 k 个点配成k/2个互不相交的对,并最大化每一对点的距离之和。

思路:

一个结论,这k条路经至少会交于一个公共点,可以证明如果没有交于一点一定存在一个更优的方案并且交于一点。

于是考虑去求所有选中的点到相交点的距离,动态维护距离,同时要保证拥有最多选中点的子树大小<=k/2,否则会有路径无法交于相交点。

以下代码:

#include<bits/stdc++.h>
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1e5+5;
bool f[N];
LL ans,dist[N],S;
int dfn[N],id,sz[N],mx[N],sum[N],out[N],rt,a[N];
int n,k,head[N],ne[N<<1],to[N<<1],w[N<<1],cnt;
il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;
}
il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;
}
il void dfs1(int x,int fa){dfn[x]=++id;sz[x]=f[x];sum[id]=sum[id-1]+f[x];if(f[x])S+=dist[x];for(int i=head[x];i;i=ne[i]){if(to[i]==fa)continue;dist[to[i]]=dist[x]+w[i];dfs1(to[i],x);sz[x]+=sz[to[i]];mx[x]=max(mx[x],sz[to[i]]);}mx[x]=max(mx[x],k-sz[x]);out[x]=id;
}
il void dfs2(int x,int fa){if(mx[x]*2<=k&&ans<S)ans=S,rt=x;for(int i=head[x];i;i=ne[i]){if(fa==to[i])continue;int tot=sum[out[to[i]]]-sum[dfn[to[i]]-1];S+=1ll*(k-(tot<<1))*w[i];dfs2(to[i],x);S-=1ll*(k-(tot<<1))*w[i];}
}
int tt=0;
vector<int> v[N];
struct node{int x,d,id;bool operator<(const node&t1)const{return d<t1.d;}
};
priority_queue<node> q;
il void dfs3(int x,int fa){if(f[x])v[tt].push_back(x);for(int i=head[x];i;i=ne[i]){if(fa==to[i])continue;dfs3(to[i],x);}
}
int main()
{n=read();k=read();for(int i=1;i<n;i++){int x=read(),y=read(),z=read();insert(x,y,z);insert(y,x,z);}for(int i=1;i<=k;i++)a[i]=read(),f[a[i]]=1;dfs1(1,0);dfs2(1,0);if(f[rt])v[++tt].push_back(rt);for(int i=head[rt];i;i=ne[i])++tt,dfs3(to[i],rt);for(int i=1;i<=tt;i++){int x=v[i].size();if(!x)continue;q.push((node){v[i][x-1],x-1,i});}for(int i=1;i<=(k>>1);i++){node a=q.top();q.pop();node b=q.top();q.pop();printf("%d %d\n",a.x,b.x);if(a.d>=1)q.push((node){v[a.id][a.d-1],a.d-1,a.id});if(b.d>=1)q.push((node){v[b.id][b.d-1],b.d-1,b.id});}return 0;
}

View Code

转载于:https://www.cnblogs.com/Jessie-/p/10416047.html

dtoj#4178. 配对(pair)相关推荐

  1. C++ 和 Java 中的 Pair 配对

    C++ 和 Java 中的 Pair 配对 \qquad 配对(Pair).配对提供了一种方便方式来处理简单的键值关联,当我们想从方法返回两个值时特别有用. Java Pair类在javafx.uti ...

  2. 如何将AirPods与Apple Watch配对

    Peter Kotoff/Shutterstock.com. 彼得·科托夫(Peter Kotoff)/Shutterstock.com. AirPods, AirPod Pros, and othe ...

  3. android 蓝牙广播协议,Android蓝牙协议-蓝牙配对与连接

    蓝牙设备在连接前,会先检查设备是否已经配对过,如果没有则先配对,配对完成后,再开始连接. onPreferenceTreeClick 蓝牙连接开始于设备列表 DeviceListPreferenceF ...

  4. BES2300x笔记----TWS组对与蓝牙配对

    https://me.csdn.net/zhanghuaishu0 一.前言 看到有"道友"在评论区留言:对TWS组对.BT配对以及回连流程部分很迷糊,那这第二篇我们就来说说BES ...

  5. pair java_介绍java中Pair

    介绍java中Pair 在这篇文章中,我们讨论了一个非常有用的编程概念,配对(Pair).配对提供了一种方便方式来处理简单的键值关联,当我们想从方法返回两个值时特别有用. 在核心Java库中可以使用配 ...

  6. hashmap 从头到尾_如何从头到尾设计一个简单的复古徽标

    hashmap 从头到尾 在纸上素描粗糙的概念 (Sketch rough concepts on paper) Start by sketching out a few ideas for your ...

  7. c语言编程时碰到取整去不了_碰到编程墙时如何解开

    c语言编程时碰到取整去不了 Getting stuck is part of being a programmer, no matter the level. The so-called " ...

  8. android 4.0 蓝牙分析之一

    原址 SystemServer启动开始讲起,在SystemServer启动的时,会启动一个BluetoothService与BluetoothA2DPService的实例: Code: //     ...

  9. 黑灰白箱测试+Ubuntu wireshark wifibluetooth

    白箱测试或白盒测试(White-box testing 或glass-box testing)是通过程序的源代码进行测试而不使用用户界面.这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条 ...

最新文章

  1. JavaScriptjQuery.stopPropogation()
  2. hyperopt中文文档:Installation-Notes安装说明
  3. putty颜色设置|securecrt颜色设置|windows命令行颜色设置
  4. redis常见应用场景
  5. python tkinter滚动条不起作用_Tkinter滚动条不工作
  6. android 集成x5内核时 本地没有,腾讯浏览服务-接入文档
  7. USACO-Section1.3 Name That Number (遍历与字符串比较)
  8. 常用电脑的人养眼绝招
  9. 【SAS Notes】If then statements
  10. Q118:PBRT-V3材质及其对应的反射模型(笔记)
  11. C刷题记录-1020
  12. android高效ORM数据库框架greenDao使用
  13. 编写一个程序求解字谜游戏问题
  14. 防止win10自动更新——指定一个错误的升级服务器地址
  15. C++模板之全特化和偏特化
  16. django批量修改table_django restframework 多对多的批量修改,基于逻辑删
  17. 【C语言】文学研究助手
  18. pdf转ppt在线转换
  19. 软件产品质量要求和测试细则-信息安全性
  20. 专业相关的计算机知识领域,计算机技术(领域)

热门文章

  1. 菜鸟要做架构师(一)——如何快速开发中小型系统
  2. 程序员面试题精选100题(31)-从尾到头输出链表[数据结构]
  3. 【人脸识别】人脸识别必读论文
  4. MATLAB语言中的关系与逻辑运算
  5. Python入门学习(四)
  6. APT团伙是如何利用Windows热修复的?
  7. parted--大于2T的分区工具
  8. js中常用的正则表达式
  9. IOS 学习笔记 2015-03-22 OC-API-日期
  10. Sqlite基础及其与SQLServer语法差异