dtoj#4178. 配对(pair)
题目描述:
由于 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)相关推荐
- C++ 和 Java 中的 Pair 配对
C++ 和 Java 中的 Pair 配对 \qquad 配对(Pair).配对提供了一种方便方式来处理简单的键值关联,当我们想从方法返回两个值时特别有用. Java Pair类在javafx.uti ...
- 如何将AirPods与Apple Watch配对
Peter Kotoff/Shutterstock.com. 彼得·科托夫(Peter Kotoff)/Shutterstock.com. AirPods, AirPod Pros, and othe ...
- android 蓝牙广播协议,Android蓝牙协议-蓝牙配对与连接
蓝牙设备在连接前,会先检查设备是否已经配对过,如果没有则先配对,配对完成后,再开始连接. onPreferenceTreeClick 蓝牙连接开始于设备列表 DeviceListPreferenceF ...
- BES2300x笔记----TWS组对与蓝牙配对
https://me.csdn.net/zhanghuaishu0 一.前言 看到有"道友"在评论区留言:对TWS组对.BT配对以及回连流程部分很迷糊,那这第二篇我们就来说说BES ...
- pair java_介绍java中Pair
介绍java中Pair 在这篇文章中,我们讨论了一个非常有用的编程概念,配对(Pair).配对提供了一种方便方式来处理简单的键值关联,当我们想从方法返回两个值时特别有用. 在核心Java库中可以使用配 ...
- hashmap 从头到尾_如何从头到尾设计一个简单的复古徽标
hashmap 从头到尾 在纸上素描粗糙的概念 (Sketch rough concepts on paper) Start by sketching out a few ideas for your ...
- c语言编程时碰到取整去不了_碰到编程墙时如何解开
c语言编程时碰到取整去不了 Getting stuck is part of being a programmer, no matter the level. The so-called " ...
- android 4.0 蓝牙分析之一
原址 SystemServer启动开始讲起,在SystemServer启动的时,会启动一个BluetoothService与BluetoothA2DPService的实例: Code: // ...
- 黑灰白箱测试+Ubuntu wireshark wifibluetooth
白箱测试或白盒测试(White-box testing 或glass-box testing)是通过程序的源代码进行测试而不使用用户界面.这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条 ...
最新文章
- JavaScriptjQuery.stopPropogation()
- hyperopt中文文档:Installation-Notes安装说明
- putty颜色设置|securecrt颜色设置|windows命令行颜色设置
- redis常见应用场景
- python tkinter滚动条不起作用_Tkinter滚动条不工作
- android 集成x5内核时 本地没有,腾讯浏览服务-接入文档
- USACO-Section1.3 Name That Number (遍历与字符串比较)
- 常用电脑的人养眼绝招
- 【SAS Notes】If then statements
- Q118:PBRT-V3材质及其对应的反射模型(笔记)
- C刷题记录-1020
- android高效ORM数据库框架greenDao使用
- 编写一个程序求解字谜游戏问题
- 防止win10自动更新——指定一个错误的升级服务器地址
- C++模板之全特化和偏特化
- django批量修改table_django restframework 多对多的批量修改,基于逻辑删
- 【C语言】文学研究助手
- pdf转ppt在线转换
- 软件产品质量要求和测试细则-信息安全性
- 专业相关的计算机知识领域,计算机技术(领域)