消防

2011年

 时间限制: 2 s
 空间限制: 256000 KB
 题目等级 : 大师 Master
 
题目描述 Description

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

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

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

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

输入描述 Input Description

输入包含n行:
    第1行,两个正整数n和s,中间用一个空格隔开。其中n为城市的个数,s为路径长度的上界。设结点编号以此为1,2,……,n。
  从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。

输出描述 Output Description

输出包含一个非负整数,即所有城市到选择的路径的最大值,当然这个最大值必须是所有方案中最小的。

样例输入 Sample Input

【样例输入1】

5 2
1 2 5
2 3 2
2 4 4
2 5 3

【样例输入2】

8 6
1 3 2
2 3 2 
3 4 6
4 5 3
4 6 4
4 7 2
7 8 3

样例输出 Sample Output

【样例输出1】

5

【样例输出2】

5

数据范围及提示 Data Size & Hint

对于20%的数据,n<=300。

对于50%的数据,n<=3000。

对于100%的数据,n<=300000,边长小等于1000。

/*
20%的数据,就是NOIP那道树网的核。
100%这么大的数据范围,若直径长度为d,dlogd可能会被卡
所以就需要一种O(n)的算法。 先bfs两遍求出树的直径(防爆栈),O(n)的
然后维护 g[i]表示i是路径右端点时,右边那段删掉的直径长度。
f[i]表示i是路径左端点时,左边那段删掉的直径长度。
h[i]表示i是直径上的点,每个直径上的点不是都有一棵(或者很多棵)
由非此直径上点组成的树(森林)嘛,点i到这些子节点中最远的那个的距离。
然后在这个序列上跑双指针。就是路径长度不是有限制嘛,然后从左到右枚举左端点,然后右端点是非严格单调右移的。
时间复杂度线性。而对于一段路径区间[l,r],它作为枢纽时的答案为
max(max(f[l],g[r]),max{hi,i∈[l,r]})
然后最右边那个怎么搞呢? 单调队列,维护hi最大值啊~
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue> #define N 3000007
#define inf 0x3f3f3f3f using namespace std;
int n,m,k,s,t,ans,cnt,num,L,R;
int head[N],f[N],g[N],h[N],fa[N],vis[N];
int belong[N],tmp[N],que[N],id[N];
struct edge{
int v,net,w;
}e[N<<];
queue<int>q; inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} inline void add(int u,int v,int w)
{
e[++cnt].v=v;e[cnt].w=w,e[cnt].net=head[u];head[u]=cnt;
} int bfs(int s,int Time)
{
int len=;q.push(s);
g[s]=,fa[s]=s,vis[s]=Time;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i;i=e[i].net)
{
int v=e[i].v;
if(vis[v]==Time) continue;
g[v]=g[u]+e[i].w;len=max(len,g[v]);
fa[v]=u;vis[v]=Time;
q.push(v);
}
}return len;
} void solve()
{
int i;
for(s=,bfs(s,++num),i=;i<=n;i++)
if(g[i]>g[s]) s=i;
for(bfs(s,++num),i=;i<=n;i++)
if(g[i]>g[t]) t=i;
belong[n=]=t;num++;
do{
t=fa[t],belong[++n]=t,vis[t]=num;
}while(t!=s); for(i=;i<=n;i++) f[i]=g[belong[]]-g[belong[i]];
for(i=;i<=n;i++) tmp[i]=g[belong[i]];
for(i=;i<=n;i++) h[i]=bfs(belong[i],num);
for(i=;i< n;i++) g[i]=tmp[i];g[n]=;
} int main()
{
int x,y,z;
n=read();m=read();
for(int i=;i<n;i++)
{
x=read();y=read();z=read();
add(x,y,z);add(y,x,z);
}
solve(); int l=,r=;ans=inf;
for(l=;l<=n;l++)
{
while(r<n && f[r+]-f[l]<=m)
{
++r;while(L<=R && que[R]<h[r]) R--;
que[++R]=h[r];id[R]=r;
}
ans=min(ans,max(max(f[l],g[r]),que[L]));
if(id[L]<=l)L++;
}
printf("%d\n",ans);
return ;
}

[SDOI2011]消防(单调队列,树的直径,双指针)的更多相关文章

  1. [BZOJ1999] 树网的核 [数据加强版] (树的直径)

    传送门 如果只是想验证算法正确性这里是洛谷数据未加强版 Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T为树网(treenet ...

  2. 【SDOI2011 第2轮 DAY1】消防 -[树的直径+树链剖分][解题报告]

    [SDOI2011 第2轮 DAY1]消防 题面: SDOI2011 第2轮 DAY1]消防 时间限制 : 20000 MS 空间限制 : 565536 KB 问题描述 时限\(2s\) 某个国家有\ ...

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

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

  4. HDU 4123(树的直径+单调队列)

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. POJ 3162 Walking Race(树的直径+单调队列)

    题目大意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到dis[1],dis[2],dis[3]……dis[n] ,在数列的dis中求一个最长的 ...

  6. HDU 4123 Bob’s Race 树的直径+单调队列

    题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...

  7. 直径上的乱搞 bzoj1999求树直径上的结点+单调队列,bzoj1912负权树求直径+求直径边

    直径上的乱搞一般要求出这条直径上的点集或者边集 bzoj1999:对直径上的点集进行操作 /* 给出一颗树,在树的直径上截取长度不超过s的路径 定义点u到s的距离为u到s的最短路径长度 定义s的偏心距 ...

  8. 与图论的邂逅01:树的直径&基环树&单调队列

    树的直径 定义:树中最远的两个节点之间的距离被称为树的直径.  怎么求呢?有两种官方的算法(不要问官方指谁我也不晓得): 1.两次搜索.首先任选一个点,从它开始搜索,找到离它最远的节点x.然后从x开始 ...

  9. 【bzoj1999】[Noip2007]Core树网的核 树的直径+双指针法+单调队列

    题目描述 给出一棵树,定义一个点到一条路径的距离为这个点到这条路径上所有点的距离的最小值.求一条长度不超过s的路径,使得所有点到这条路径的距离的最大值最小. 输入 包含n行: 第1行,两个正整数n和s ...

随机推荐

  1. STM32F407 新建基于固件库的项目模板

    1.新建文件夹如图: 2.新建项目在USER文件夹中,选cpu如图: 若再弹出窗口, 直接点cancel 3.删了这俩文件夹: 4.复制文件到fwlib: src 存放的是固件库的.c 文件, inc ...

  2. HDU-3790最短路径问题,第十遍终于过了~

    最短路径问题                                                                   Time Limit: 2000/1000 MS (J ...

  3. ORACLE数据库查看执行计划的方法

    一.什么是执行计划(explain plan) 执行计划:一条查询语句在ORACLE中的执行过程或访问路径的描述. 二.如何查看执行计划 1: 在PL/SQL下按F5查看执行计划.第三方工具toad等 ...

  4. POJ1094 字母排序(拓扑排序)

    该题题意明确,就是给定一组字母的大小关系判断他们是否能组成唯一的拓扑序列.是典型的拓扑排序,但输出格式上确有三种形式: 1.该字母序列有序,并依次输出: 2.该序列不能判断是否有序: 3.该序列字母次 ...

  5. mysql常用jar包

    连接Mysql数据库: 常用的连接池有两种 DBCP连接池 C3P0连接池 Apache的commons组件 -- DBCP连接池: commons-dbutils-1.4.jar 封装并简化了JDB ...

  6. 洛谷 P2064 奇妙的汽车

    P2064 奇妙的汽车 题目描述 你有着一辆奇妙的汽车,这辆汽车有着自动加速的功能.打个比方吧,第1天你驾驶着它可以行驶a路程,那么第2天你可以让它所走的路程增加到第1天的2~9倍(必须是其中一个整数 ...

  7. Ubuntu 16.04下Redis Cluster集群搭建(官方原始方案)

    前提:先安装好Redis,参考:http://www.cnblogs.com/EasonJim/p/7599941.html 说明:Redis Cluster集群模式可以做到动态增加节点和下线节点,使 ...

  8. How to remote debug neutron

    First of all, I will assume that you know how to use pydevd to remote debug normal python program. I ...

  9. mybatis resultmap标签type属性什么意思

    mybatis resultmap标签type属性什么意思? :就表示被转换的对象啊,被转换成object的类型啊 <resultMap id="BaseResultMap" ...

  10. webpack-输出

    输出(Output) 配置 output 选项可以控制 webpack 如何向硬盘写入编译文件. 注意,即使可以存在多个入口起点,但只指定一个输出配置. 用法(Usage) 在 webpack 中配置 ...