洛谷 P2491 解题报告
P2491 消防
题目描述
某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000)。
这个国家的人对火焰有超越宇宙的热情,所以这个国家最兴旺的行业是消防业。由于政府对国民的热情忍无可忍(大量的消防经费开销)可是却又无可奈何(总统竞选的国民支持率),所以只能想尽方法提高消防能力。
现在这个国家的经费足以在一条边长度和不超过s的路径(两端都是城市)上建立消防枢纽,为了尽量提高枢纽的利用率,要求其他所有城市到这条路径的距离的最大值最小。
你受命监管这个项目,你当然需要知道应该把枢纽建立在什么位置上。
输入输出格式
输入格式:
输入包含n行:
第1行,两个正整数n和s,中间用一个空格隔开。其中n为城市的个数,s为路径长度的上界。设结点编号以此为1,2,……,n。
从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。
输出格式:
输出包含一个非负整数,即所有城市到选择的路径的最大值,当然这个最大值必须是所有方案中最小的。
说明
【数据规模和约定】
对于20%的数据,n<=300。
对于50%的数据,n<=3000。
对于100%的数据,n<=300000,边长小等于1000。
对于消防局的建设的地点,选择在树的直径上是最优的。
树的直径:树中的最长简单路
- 证明:
假设消防局为黄链\(A\)(\(A\)不在\(D\)上),其中有点\(A_1\),\(A_2\)......\(A_n\),树的某一直径为蓝链\(D\),两边的点分别为\(D_1\),\(D_2\)
则对于点\(A_i\)来说,在整颗树中最远的点即为\(D_1\)或\(D_2\)
证明(证明中的证明):
假设存在\(S_2\)使得\(D_3\)距离Ai最远,则必有\(S_2+S_1>S_4\)(或\(S_3\)),即产生了新的直径,不成立,得证。
由以上可知,黄链上的点到外面最远的一个点的距离为
\(Dis=min\{E(A_i,D_1),E(A_i,D_2),i\in[1,n]\}\)
若令\(dis\)最小,则链\(A\)必在链\(D\)上。
但是,当\(A\)在\(D\)上时,链\(A\)到外面的点(即不在直径上的点)的距离\(f\)是可能大于\(dis\)的,是合法的。
这样是否矛盾?
不矛盾,因为任何一个在外面的链\(A\)的\(dis\)都是大于在直径上的链\(A\)的\(f\)的
其实不太严谨哈
那么对于这个题,我们就有了思路啊
2次dfs求出树的直径(第一次求出某条直径端点,第二次直接抽出直径)
预处理直径上每个点\(i\)向外延伸的最长距离\(c[i]\)
对于待检验链\(A\),左端为\(A_i\),右端为\(A_j\),此时的最长距离即为\(max\{E(A_1,A_i),E(A_j,A_n),c[k],k\in[i,j]\}\)
前两个好弄,前缀和就行。
后一个是\(RMQ\)问题,\(ST\)表线段树维护一下就行。
但还有个更优的,我们注意到我们相当于拿一个窗口划过了链\(A\),对啊,妥妥的单调队列维护啊
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int N=300010;
int n,s;
int used[N];
struct node1
{
int i,w;
node1(){}
node1(int i,int w)
{
this->i=i;
this->w=w;
}
};
deque <node1> q;
struct node
{
int i,w;
node(){}
node(int i,int w)
{
this->i=i;
this->w=w;
}
};
vector <node > g[N];
int l,m_max=0;
int son[N],ww[N];
int c[N];//节点i外面的最长边
void dfs0(int now,int len)
{
used[now]=true;
if(m_max<len)
{
m_max=len;
l=now;
}
for(int i=0;i<g[now].size();i++)
{
int v=g[now][i].i,w=g[now][i].w;
if(!used[v])
dfs0(v,w+len);
}
}
void dfs1(int now)
{
used[now]=true;
for(int i=0;i<g[now].size();i++)
{
int v=g[now][i].i,w=g[now][i].w;
if(!used[v])
{
dfs1(v);
if(ww[v]+w>ww[now])
{
ww[now]=ww[v]+w;
son[now]=v;
}
}
}
}
int dfs(int now)
{
int mmax=0;
used[now]=1;
for(int i=0;i<g[now].size();i++)
{
int v=g[now][i].i,w=g[now][i].w;
if(!used[v])
mmax=max(dfs(v)+w,mmax);
}
return mmax;
}
int a[N],f[N];
int main()
{
cin>>n>>s;
int u,v,w;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
node tt(v,w);
g[u].push_back(tt);
tt.i=u;
g[v].push_back(tt);
}
memset(used,0,sizeof(used));
dfs0(1,0);//找到左端点
memset(used,0,sizeof(used));
memset(son,0,sizeof(son));
memset(ww,0,sizeof(ww));
dfs1(l);//存储直径
memset(used,0,sizeof(used));
int now=l;
int cnt=0;
while(now)
{
used[now]=1;
a[++cnt]=now;
now=son[now];
}
now=l;
cnt=0;
while(now)
{
c[++cnt]=dfs(now);
now=son[now];
}
for(int i=1;i<=cnt;i++)
f[i]=ww[a[i]];
int ans=0x3f3f3f3f,ll=1;
for(int i=1;i<=cnt;i++)
{
node1 tt(i,c[i]);
while(!q.empty()&&c[i]>q.front().w) q.pop_front();
q.push_front(tt);
while(f[ll]-f[i]>s)
{
ll++;
if(q.back().i<ll)
q.pop_back();
}
ans=min(ans,max(f[1]-f[ll],max(f[i],q.back().w)));
}
cout<<ans<<endl;
return 0;
}
结论:
- 两遍DFS求树的直径
- 权有上界的 以最小代价联通整个树的 链在树的直径上
2018.4.27
洛谷 P2491 解题报告的更多相关文章
- 洛谷 P1462 解题报告
P1462 通往奥格瑞玛的道路 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡 ...
- 洛谷 P1879 解题报告
P1879 [USACO06NOV]玉米田Corn Fields 题目描述 农场主\(John\)新买了一块长方形的新牧场,这块牧场被划分成\(M\)行\(N\)列\((1 ≤ M ≤ 12; 1 ≤ ...
- 洛谷 P1069 解题报告
P1069 细胞分裂 题目描述 \(Hanks\)博士是\(BT\) (\(Bio-Tech\),生物技术) 领域的知名专家.现在,他正在为一个细胞实验做准备工作:培养细胞样本. \(Hanks\) ...
- 洛谷 P2587 解题报告
P2587 [ZJOI2008]泡泡堂 题目描述 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏 ...
- 洛谷 P1054 解题报告
P1054 等价表达式 题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的 ...
- 洛谷 P1053 解题报告
P1053 篝火晚会 题目描述 佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了"小教官".在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会.一共有 ...
- 洛谷 P1057 解题报告
P1057 传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹 ...
- 洛谷 P1430 解题报告
P1430 序列取数 题目描述 给定一个长为\(n\)的整数序列\((n<=1000)\),由\(A\)和\(B\)轮流取数(\(A\)先取).每个人可从序列的左端或右端取若干个数(至少一个), ...
- 洛谷 P1613 解题报告
P1613 跑路 题目描述 小\(A\)的工作不仅繁琐,更有苛刻的规定,要求小\(A\)每天早上在\(6:00\)之前到达公司,否则这个月工资清零.可是小\(A\)偏偏又有赖床的坏毛病.于是为了保住自 ...
随机推荐
- my golib:db query Result
go提供了一套统一操作database的sql接口,任何第三方都可以通过实现相应的driver来访问感兴趣的数据库.譬如我们项目中使用的Go-MySQL-Driver. go提供了一套很好的机制来处理 ...
- Swift的基础之关于“!”和“?”的使用介绍
swift编程,不外乎是定义属性或者函数(方法),访问属性或者调用函数,类型转换,?和!在这几个过程中,都有一展身手的时候,而且,每次要考虑使用的时候,它们俩都会一起出现在我们的大脑中,用还是不用,如 ...
- Swift的基础之UILabel控件
对于UILabel的相关内容,其他控件可以相似创建 //设置全局变量,将下面的 let 去掉,然后替换即可 //var myLabel = UILabel(); //系统生成的view ...
- RHEL6下获取安装包(RPM)而不安装的方法
RHEL6下获取安装包(RPM)而不安装的方法 有时候我们只能在某个机器上网获得RPM安装包,如何将RPM包在不能上网的内网机器安装,就需要能将安装包下载到本地而不安装,然后再把这些包复制到内网机器, ...
- LDA主体模型
一)LDA作用 传统判断两个文档相似性的方法是通过查看两个文档共同出现的单词的多少,如TF-IDF等,这种方法没有考虑到文字背后的语义关联,可能在两个文档共同出现的单词很少甚至没有,但两个文档是相似的 ...
- SpriteBuilder中如何固定两个互不接触的物理物体?
如下图: 这个弹簧装置由3部分组成(从上到下): 弹板 弹簧 弹簧金属底座 其中弹板将固定在弹簧上(但并没有接触,如上图),这就引出一个有趣的问题:怎么样才能将两个独立的物理物体(注意:是物理物体)固 ...
- 从硬件竞争到软实力PK——电视媒体竞争观察
本文观点及数据摘自中广研究<三网融合月度精粹>第26期(2013年2月版),详细参考对应在线简版(http://doc.sarft.net/index.php?f=2013/02/2013 ...
- Mondrian Schema workbench工作界面 简介(实在懒得写,居然有人弄了,收藏了)
转自:http://hi.baidu.com/dinguangx/item/37e78be29aebc1adcf2d4f89 Schema Schema 定义了一个多维数据库.包含了一个逻辑模型,而这 ...
- HOW to Use QP_PREQ_PUB.PRICE_REQUEST API to Price an Item
In this Document Goal Solution References APPLIES TO: Oracle Advanced Pricing - Version 11.5.10 ...
- Sample Code for Qp_preq_pub.Price_request Api to Simulate an Ask for Promotion Modifier
DECLARE p_line_tbl QP_PREQ_GRP.LINE_TBL_TYPE; p_qual_tbl QP_PREQ_GRP.QUAL_TBL_TYPE; p_line_attr_tbl ...