$Noip2018/Luogu5021$ 赛道修建 二分+树形
$Sol$
一直以为是每个点只能经过一次没想到居然是每条边只能经过一次$....$
首先其实这题$55$分的部分分真的很好写啊,分别是链,数的直径和菊花图,这里就不详细说了.
使得修建的$m$条赛道中长度最小的赛道长度最大有了这句话显然就要考虑考虑二分.现在就是要考虑如何判断了.
任意选择结点作为根建树.注意到一条赛道的组成其实只有两种,一种是一条简单的由浅到深的链,另一种是由深到浅再到深这样的折了一下的链.考虑由深到浅的处理结点.对于每个结点,把子结点上传的链长加上父与子之间的边权加入$mutiset$.首先找到值已经大于等于$mid$的,直接累计答案.然后考虑内部匹配,从小到大扫,找到另一个最小的使得两者相加大于等于$mid$的值,删去这俩结点并且累计答案.最后向父结点上传剩余的链里面最长的就行.
$Code$
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
#define il inline
#define Rg register
#define go(i,a,b) for(Rg int i=a;i<=b;++i)
#define yes(i,a,b) for(Rg int i=a;i>=b;--i)
#define e(i,u) for(Rg int i=b[u];i;i=a[i].nt)
#define mem(a,b) memset(a,b,sizeof(a))
#define v(i) a[i].v
#define w(i) a[i].w
#define ll long long
#define db double
#define IT multiset<ll>::iterator
#define inf 2147483647
using namespace std;
il int read()
{
Rg int x=,y=;char c=getchar();
while(c<''||c>''){if(c=='-')y=-;c=getchar();}
while(c>=''&&c<=''){x=(x<<)+(x<<)+c-'';c=getchar();}
return x*y;
}
const int N=;
int n,m,b[N],ct;
ll d1[N],d2[N],l=inf,r,mid,as;
struct node{int v,w,nt;}a[N*];
il void add(int u,int v,int w){a[++ct]=(node){v,w,b[u]};b[u]=ct;}
il void dfs1(int u,int ft)
{
e(i,u)
{
if(v(i)==ft)continue;
dfs1(v(i),u);
if(d1[v(i)]+w(i)>d1[u]){d2[u]=d1[u];d1[u]=d1[v(i)]+w(i);}
else d2[u]=max(d2[u],d1[v(i)]+w(i));
}
}
il ll dfs(int u,int fa)
{
multiset<ll>q;q.clear();
e(i,u)
{
if(v(i)==fa)continue;
ll val=dfs(v(i),u)+w(i);
if(val>=mid)ct++;
else q.insert(val);
}
ll ret=;
while(q.size())
{
IT i=q.begin();
IT j=q.lower_bound(mid-*i);
if(((i==j)&&q.count(*i)==))j++;
if(j==q.end()){ret=max(ret,*i);q.erase(i);continue;}
ct++;q.erase(q.find(*i));q.erase(q.find(*j));
}
return ret;
}
il bool ck()
{
ct=;dfs(,);
if(ct>=m)return ;return ;
}
int main()
{
n=read(),m=read();
go(i,,n-){Rg int u=read(),v=read(),w=read();add(u,v,w);add(v,u,w);l=min(l,(ll)w);}
dfs1(,);
go(i,,n)r=max(r,d1[i]+d2[i]);
if(m==){printf("%lld\n",r);return ;}
r+=;
while(l<=r)
{
mid=(l+r)>>;
if(ck())as=mid,l=mid+;
else r=mid-;
}
printf("%lld\n",as);
return ;
}
随机推荐
- python----操作Memcache、redis、RabbitMQ、SQLAlchemy
操作本质都是通过socket发送命令 Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次 ...
- Python深入:01内存管理
在Python中,一切都是指针. 一:对象三特性 所有的Python对象都有三个特性:身份,类型和值. 身份:每一个对象都有一个唯一的身份标识,任何对象 ...
- @NOI模拟2017.06.30 - T3@ Right
目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ JOHNKRAM 和 ...
- Android Animation动画实战(一): 从布局动画引入ListView滑动时,每一Item项的显示动画
前言: 之前,我已经写了两篇博文,给大家介绍了Android的基础动画是如何实现的,如果还不清楚的,可以点击查看:Android Animation动画详解(一): 补间动画 及 Android An ...
- CSS像素设置为整数,渲染结果像素带有小数
今天进行网页设计学习时,CSS代码设计width:300px,但实际显示像素如下图所示为199.99px. 最后发现是浏览器运用了缩放,恢复100%的缩放后,像素显示为整数.
- SpringMVC参数校验,包括JavaBean和基本类型的校验
该示例项目使用SpringBoot,添加web和aop依赖. SpringMVC最常用的校验是对一个javaBean的校验,默认使用hibernate-validator校验框架.而网上对校验单个参数 ...
- spring boot + thymeleaf 乱码问题
spring boot + thymeleaf 乱码问题 hellotrms 发布于 2017/01/17 15:27 阅读 1K+ 收藏 0 答案 1 开发四年只会写业务代码,分布式高并发都不会还做 ...
- 关于后台动态模板添加内容的总结 Builder使用
1.后台控制器中ArticleController中加载 formBuilder,listBuilder类: 2.实例化FormBuilder对象,调用类中的方法: 3.初始化时加载Builder/f ...
- 剑指 Offer —— 数组中重复的数字
数组中的重复数字 题目描述 牛课网链接 长度为 n 的数组里,所有数字都在 0 到 n-1 的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一 ...
- CCPC 2018 吉林 H "LOVERS" (线段树)
---恢复内容开始--- 传送门 参考资料: [1]:https://blog.csdn.net/mmk27_word/article/details/89788448 题目描述: The Fool ...