$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 ;
}
随机推荐
- Flask学习之九 分页
英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ix-pagination 中文翻译地址:http:// ...
- IO NIO AIO及常用框架概述
概述 nio 同步: 自己亲自出马持银行卡到银行取钱(使用同步IO时,Java自己处理IO读写). 异步: 委托一小弟拿银行卡到银行取钱,然后给你(使用异步IO时,Java将IO读写委托给OS处理,需 ...
- 洛谷 2152 [SDOI2009]SuperGCD
Description Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比赛计算GCD.有一天Sheng bill很嚣张地找到了你,并要 ...
- C++ 第四次作业 继承
继承 继承时从新的类从已有类那里得到新的特征.继承实现了代码的重用,极大地减少了代码量,同时通过新增成员,加入了自身的独有特性,达到了程序的扩充. 派生类继承了基类的全部数据类和除了构造函数.析构函数 ...
- LA 4973 Ardenia (3D Geometry + Simulation)
ACM-ICPC Live Archive 三维几何,题意是要求求出两条空间线段的距离.题目难度在于要求用有理数的形式输出,这就要求写一个有理数类了. 开始的时候写出来的有理数类就各种疯狂乱套,TLE ...
- oracle 需要当心的WHERE子句
某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. 在下面的例子里, ‘!=’ 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. 不使用索引: ...
- OP_REQUIRES failed at conv_ops.cc:386 : Resource exhausted: OOM when allocating tensor with shape..
tensorflow-gpu验证准确率是报错如上: 解决办法: 1. 加入os.environ['CUDA_VISIBLE_DEVICES']='2' 强制使用CPU验证-----慢 2.'batch ...
- H3C 对等通信
- svcs (service status) 和 svcadm (service administration) 使用
1. svcs 显示服务实例的状态信息 svcs - report service status 显示服务状态命令 DESCRIPTION The svcs command displays in ...
- Html5 @media + css3 媒体查询
css3 media媒体查询器用法总结 随着响应式设计模型的诞生,Web网站又要发生翻天腹地的改革浪潮,可能有些人会觉得在国内IE6用户居高不下的情况下,这些新的技术还不会广泛的蔓延下去,那你就错 ...