$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 ;
}
随机推荐
- Django ORM------Mysql
ORM操作 select * from tb where id > 1 #对应关系 models.tb.objects.filter(id__gt=1) models.tb.objects.fi ...
- oracle 和 mysql 遍历当前月份每一天
获取当前月份的每一天的数据 oracle SELECT TO_DATE(TO_CHAR(SYSDATE, 'YYYYMM'), 'YYYYMM') + (ROWNUM - 1) DAY_ID FROM ...
- C# 设计模式 责任链
责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...
- @topcoder - SRM697D1L3@ ConnectedStates
目录 @description@ @solution@ @accepted code@ @details@ @description@ 有n个城市,每个城市有个权值wi,任意两个城市i,j之间的道路数 ...
- mysql数据库之mysql下载与设置
下载和安装mysql数据库 mysql为我们提供了开源的安装在各个操作系统上的安装包,包括ios,liunx,windows. mysql的安装,启动和基础配置-------linux版本 mysql ...
- 微信小程序弹框wx.showModal如何修改样式
由于官方API提供的显示模态弹窗,只能简单地显示文字内容,不能对对话框内容进行自定义,欠缺灵活性,所以自己从模态弹窗的原理角度来实现了自定义的模态对话框. wx.showModal修改样式后的效果,如 ...
- Nginx 的 location
一.location语法 语法: Syntax: location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... } Default: — ...
- Java RandomAccessFile用法(转载)
RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须 ...
- Python--day27--设计模式
设计模式:单例模式
- 2018-2-13-C#-枚举转字符串
title author date CreateTime categories C# 枚举转字符串 lindexi 2018-2-13 17:23:3 +0800 2018-2-13 17:23:3 ...