某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000)。

这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的行业是消防业。由于政府对国民的热情忍无可忍(大量的消防经费开销)可是却又无可奈何(总统竞选的国民支持率),所以只能想尽方法提高消防能力。

现在这个国家的经费足以在一条边长度和不超过s的路径(两端都是城市)上建立消防枢纽,为了尽量提高枢纽的利用率,要求其他所有城市到这条路径的距离的最大值最小。

你受命监管这个项目,你当然需要知道应该把枢纽建立在什么位置上。

Solution

这题非常神,神在它有一堆解法。

首先考虑无脑暴力,枚举一个起点,一个终点,O(n)算出最长距离,更新答案,复杂度O(n^3)。

然后根据贪心的想法,我们选择的链一定在树的直径上。

设直径端点为s和t

我们可以扫描直径上的每个点,对于每个点确定唯一的最远距离,在DFS一遍更新答案,复杂度O(n^2)。

然后发现答案具有单调性,可以二分一个答案,在直径两端贪心的找出能达到的不超过答案的最远点,DFS一遍检查合法性,复杂度O(nlogn)

继续观察我们可以发现,对于直径上的一个点i,我们要确定一个j使得max(dis(s,i),dis(j,t),sigma(d[k]))最小

d[k]表示从k点出发不经过直径上任何一个点能达到的最远距离,预处理可以得到。

于是O(n)的做法就出现了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 300002
using namespace std;
queue<int>q;
bool vis[N];
int dis[N],tot,head[N],l1[N],nex[N],num,id,id2,s,n,ans,di,dis1[N],dis2[N],pre[N],l2[N];
struct zzh{
int n,to,l;
}e[N<<];
inline void add(int u,int v,int l){
e[++tot].n=head[u];
e[tot].to=v;
head[u]=tot;
e[tot].l=l;
}
void dfs(int u,int fa){
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;
dfs(v,u);
if(!vis[v])dis[u]=max(dis[u],dis[v]+e[i].l);
}
}
int main(){
scanf("%d%d",&n,&s);int u,v,w,an=;
for(int i=;i<n;++i)scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
q.push();vis[]=;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
dis[v]=dis[u]+e[i].l;
vis[v]=;
q.push(v);
}
}
for(int i=;i<=n;++i)if(dis[i]>an){
id=i;
an=dis[i];
}
an=;memset(dis,,sizeof(dis));memset(vis,,sizeof(vis));
q.push(id);vis[id]=;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].n)if(!vis[e[i].to]){
int v=e[i].to;
dis[v]=dis[u]+e[i].l;
pre[v]=u;
l2[v]=e[i].l;
vis[v]=;
q.push(v);
}
}
for(int i=;i<=n;++i)if(dis[i]>an){
an=dis[i];
id2=i;
}
memset(dis,,sizeof(dis));memset(vis,,sizeof(vis));
ans=0x3f3f3f3f;
for(int i=id2;i!=id;i=pre[i])l1[pre[i]]=l2[i],nex[pre[i]]=i;
for(int i=id;i!=id2;i=nex[i])vis[i]=,dis1[i]=di,di+=l1[i];vis[id2]=;dis1[id2]=di;
for(int i=id;i!=id2;i=nex[i])dis2[i]=di-dis1[i]; dis2[id2]=di-dis1[id2];
dfs(id,);int diss=id;
for(int i=id;i;i=nex[i]){
while(dis1[diss]-dis1[i]+l1[diss]<=s&&diss!=id2)diss=nex[diss];
// cout<<i<<" qwq"<<diss<<" "<<dis1[i]<<" "<<dis2[diss]<<endl;
ans=min(ans,max(dis1[i],dis2[diss]));
if(diss==i)diss=nex[diss];
if(i==id2)break;
}
for(int i=;i<=n;++i)if(vis[i])ans=max(ans,dis[i]);
cout<<ans;
return ;
}

[SDOI2011]消防的更多相关文章

  1. [洛谷P2491] [SDOI2011]消防

    洛谷题目链接:[SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超 ...

  2. 【BZOJ2282】[Sdoi2011]消防 树形DP+双指针法+单调队列

    [BZOJ2282][Sdoi2011]消防 Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这 ...

  3. [SDOI2011]消防(树的直径)

    [SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情, ...

  4. Bzoj 2282: [Sdoi2011]消防(二分答案)

    2282: [Sdoi2011]消防 Time Limit: 10 Sec Memory Limit: 512 MB Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条 ...

  5. [SDOI2011]消防(贪心,图论,树的直径)

    [SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情, ...

  6. bzoj 2282 [Sdoi2011]消防(树的直径,二分)

    Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家 ...

  7. BZOJ1999或洛谷1099&BZOJ2282或洛谷2491 树网的核&[SDOI2011]消防

    一道树的直径 树网的核 BZOJ原题链接 树网的核 洛谷原题链接 消防 BZOJ原题链接 消防 洛谷原题链接 一份代码四倍经验,爽 显然要先随便找一条直径,然后直接枚举核的两个端点,对每一次枚举的核遍 ...

  8. [SDOI2011]消防/[NOIP2007] 树网的核

    消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的 ...

  9. [SDOI2011]消防(单调队列,树的直径,双指针)

     消防 2011年  时间限制: 2 s  空间限制: 256000 KB  题目等级 : 大师 Master   题目描述 Description 某个国家有n个城市,这n个城市中任意两个都连通且有 ...

随机推荐

  1. [转帖]TLS 1.3 VS TLS 1.2,让你明白 TLS 1.3 的强大

    TLS 1.3 VS TLS 1.2,让你明白 TLS 1.3 的强大 https://www.jianshu.com/p/efe44d4a7501?utm_source=oschina-app 又拍 ...

  2. 调整分区大小 转载--------------http://blog.csdn.net/perfectzq/article/details/73606119

    centos7重新调整分区大小 centos 7 调整 root 和 home 的容量大小 查看磁盘的空间大小: df -h  备份/home : cp -r /home/ homebak/ 卸载​  ...

  3. Oracle NVL空值处理函数

    --NVL空值处理函数 --需求:显示价格表中业主类型ID为1的价格记录 如果上限值为null,则显示9999999 ) from dual; select * from t_pricetable ) ...

  4. 利用js给datalist或select动态添加option选项

    <!DOCTYPE html> <html> <head> <title>鼠标点击时加载</title> <script type=& ...

  5. Unit 2.前端之html--table(表格),form(表单)标签

    一.table标签 作用:定义html表格.一个table标签元素至少包含 thead(表头),tbody(表主题),还可以有tfoot(表底部) html表格游table元素及一个或者多个tr,th ...

  6. CSS3 Flexbox轻巧实现元素的水平居中和垂直居中

    CSS3 Flexbox轻松实现元素的水平居中和垂直居中 网上有很多关于Flex的教程,对于Flex的叫法也不一,有的叫Flexbox,有的叫Flex,其实这两种叫法都没有错,只是Flexbox旧一点 ...

  7. 排查 Maxwell can not find database 并且使用 MySQL binlog 解决相关问题

    目前我们在使用 Maxwell 在读线上机器的 binlog 同步我们的离线数据库. 这次错误定位上,首先线要确定问题是发生在生产者 还是队列 还是消费者.经过查看各机器上任务的运行日志,定位到了问题 ...

  8. kprobe原理解析

    参考  http://www.cnblogs.com/honpey/p/4575928.html kprobe是linux内核的一个重要特性,是一个轻量级的内核调试工具,同时它又是其他一些更高级的内核 ...

  9. umask 文件默认权限

    参考资料 http://book.51cto.com/art/200709/57189.htm umask就是指定当前用户在建立文件或目录时候的属性默认值. linux-xdYUnA:~ # umas ...

  10. SQL Server中的完全连接(full join)

    一.建库和建表 create database scort use scort create table emp ( empno int primary key, ename ), sal int, ...