题目链接:快餐店

  震惊!某ZZ选手此题调了一天竟是因为……>>点击查看

  一般碰到这种基环树的题都要先想想树上怎么做。这道题如果是在树上的话……好像求一遍直径就做完了?答案就是直径长度的一半……

  然后我们来考虑一下基环树上的情况。假设我们选中了一个位置\(u\)作为快餐店,那么环上的有一条边是没有用的,也就是说\(u\)到其它所有点的最短路都不会经过这条边。于是,我们就可以枚举删掉环上每条边,就需要快速统计剩下这棵树的直径。如果这课树的直径没有经过环上的边,那么我们是可以通过预处理环上每棵树的直径来得到的。于是,我们接下来只考虑直径经过换上的边的情况。

  为了方便讲述,假设环上的点的编号为\(1\)到\(m\),\(1\)到\(x\)的边权和为\(w_x\)。首先,我们需要预处理环上每个点\(u\)为根往下的最长链\(f_u\)。然后,我们其实预处理几个数组即可(这里只考虑前缀),包括\(pre_i\),表示环上只用\([1,i]\)这些点组成的最长的链。由于\(pre_i=\max\{f_u+f_v+w_u-w_v\}(u>v)\),所以我们还需要维护一下\(f_x+w_x\),\(f_x-w_x\)的前缀最大值,然后每次更新即可。注意为了避免选出了两个重复的点,可以每次使用\(f_u+w_u+\max\{f_v-w_v\}(v<u)\)和\(pre_{u-1}\)来更新\(pre_u\)。类似的可以对后缀求出对应的数组。

  然后,我们在枚举环上断哪条边的时候只需要分三种情况讨论即可。假设我们断了边\((u,u+1)\),那么假设环上最优的两个点为\(i,j(i<j)\),那么要么\(1 \le i < j \le u\),要么\(u+1 \le i < j \le m\),还有\(1\le i \le u\)且\(u+1\le j \le m\)。分别用我们预处理出来的结果算出来,取个\(\max\)就是直径。最后把所有直径的\(\min\)和不过环的直径取个\(\max\)就是最终答案的两倍。

  然后我递归的时候函数名打错了……然后就到了另外一个函数里面去了……然后一天就这么过去了(捂脸

  你不要说我开头那个链接是在骗你吗……你看这里不是讲了原因么→_→

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout);
#define maxn 100010
#define maxm 200010
#define INF (1LL<<60) using namespace std;
typedef long long llg; int head[maxn],next[maxm],to[maxm],c[maxm],tt;
int n,m,fa[maxn],dfn[maxn],a[maxn];
llg dep[maxn],ans,f[maxn],b[maxn];
llg su[maxn],pr[maxn],qi[maxn][2],ho[maxn][2];
bool vis[maxn]; int getint(){
int w=0,q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') q=1,c=getchar();
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} void link(int x,int y){
to[++tt]=y;next[tt]=head[x];head[x]=tt;
to[++tt]=x;next[tt]=head[y];head[y]=tt;
c[tt-1]=c[tt]=getint();
} void work(int rt,int u){
while(u!=fa[rt]){
a[++m]=u; vis[u]=1; u=fa[u];
b[m+1]=dep[a[m]]-dep[u];
}
for(int i=1;i<=m;i++) b[i]+=b[i-1];
} void dfs(int u){
dfn[u]=++tt;
for(int i=head[u],v;v=to[i],i;i=next[i])
if(v!=fa[u] && !dfn[v]){
dep[v]=dep[u]+c[i];
fa[v]=u,dfs(v);
}
for(int i=head[u],v;v=to[i],i;i=next[i])
if(fa[v]!=u && dfn[v]>dfn[u]) b[1]=c[i],work(u,v);
} void dp(int u){
vis[u]=1;
for(int i=head[u],v;v=to[i],i;i=next[i])
if(!vis[v]){
dp(v); ans=max(ans,f[u]+f[v]+c[i]);
f[u]=max(f[u],f[v]+c[i]);
}
} void solve(){
qi[0][0]=ho[m+1][0]=pr[0]=-INF;
qi[0][1]=ho[m+1][1]=su[m+1]=-INF;
for(int i=1,u;u=a[i],i<=m;i++){
qi[i][0]=max(qi[i-1][0],f[u]+b[i]-b[1]);
qi[i][1]=max(qi[i-1][1],f[u]-b[i]+b[1]);
pr[i]=max(pr[i-1],f[u]+b[i]-b[1]+qi[i-1][1]);
}
for(int i=m,u;u=a[i],i>=1;i--){
ho[i][0]=max(ho[i+1][0],f[u]-b[i]+b[m]);
ho[i][1]=max(ho[i+1][1],f[u]+b[i]-b[m]);
su[i]=max(su[i+1],f[u]-b[i]+b[m]+ho[i+1][1]);
}
llg g=pr[m],now=0;
for(int i=1;i<m;i++){
now=b[1]+qi[i][0]+ho[i+1][0];
now=max(now,max(pr[i],su[i+1]));
g=min(g,now);
}
ans=max(ans,g);
} int main(){
File("a");
n=getint();
for(int i=1;i<=n;i++) link(getint(),getint());
tt=0; dfs(1);
for(int i=1;i<=m;i++) dp(a[i]);
solve();
printf("%.1lf",ans/2.0);
return 0;
}

  BZOJ提交网址:BZOJ 3242 快餐店

UOJ #126 【NOI2013】 快餐店的更多相关文章

  1. bzoj 3242: [Noi2013]快餐店 章鱼图

    3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 266  Solved: 140[Submit][Status] ...

  2. [UOJ#122][NOI2013]树的计数

    [UOJ#122][NOI2013]树的计数 试题描述 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的 DFS 序以及 BFS 序.两棵不同的树的 DFS 序 ...

  3. P1399 [NOI2013] 快餐店 方法记录

    原题题面P1399 [NOI2013] 快餐店 题目描述 小 T 打算在城市 C 开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小 T 希望快餐店的地址选在离最 ...

  4. UOJ#126【NOI2013】快餐店

    [NOI2013]快餐店 链接:http://uoj.ac/problem/126 YY了一个线段树+类旋转卡壳的算法.骗了55分.还比不上$O(n^2)$暴力T^T 题目实际上是要找一条链的两个端点 ...

  5. 【BZOJ3242】【UOJ#126】【NOI2013】快餐店

    NOI都是这种难度的题怎么玩嘛QAQ 原题: 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. ...

  6. 【BZOJ 3242】【UOJ #126】【CodeVS 3047】【NOI 2013】快餐店

    http://www.lydsy.com/JudgeOnline/problem.php?id=3242 http://uoj.ac/problem/126 http://codevs.cn/prob ...

  7. NOI2013 快餐店

    http://uoj.ac/problem/126 总的来说,还是很容易想的,就是有点恶心. 首先,很明显只有一个环. 我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个 ...

  8. 【uoj126】 NOI2013—快餐店

    http://uoj.ac/problem/126 (题目链接) 题意 求基环树直径. Solution zz选手迟早退役,唉,右转题解→_→:LCF 细节 拓扑排序的时候度数为0时入队.我在想什么w ...

  9. bzoj3242 [Noi2013]快餐店

    Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...

随机推荐

  1. 小强版之无码理解C语言指针

     1. 先从普通变量开始   2. 撸完变量撸指针   3. 故事情节进一步发展,此处少儿不宜   4. 奶茶妹妹捉奸,小强死定了   5. 源码欣赏  #include <stdio.h> ...

  2. MySQL(MariaDB)基础之一:编译安装

    一.cmake介绍 cmake的重要特性之一是其独立于源码的编译功能,即编译工作可以在另一个指定的目录中而非源码目录中进行,这可以保证源码目录不受任何一次编译影响,因此在同一个源码树上可以进行多次不同 ...

  3. 利用jsencrypt 做非对称加密

    1.生成 private key openssl genrsa -out rsa_1024_priv.pem 1024 2.生成public key openssl rsa -pubout -in r ...

  4. 最新Microsoft Edge!使用chromium内核

    2018年11月,微软宣布其Edge浏览器将采用Chromium引擎,意味着微软的Edge浏览器以失败告终. 但令人振奋的是,新版Edge也许会“死而复生”.在使用了Chromium内核后,Edge各 ...

  5. 机器学习之k-最近邻(kNN)算法

    一.kNN(k-nearest neighbor)算法原理 事物都遵循物以类聚的思想,即有相同特性的事物在特征空间分布上会靠得更近,所以kNN的思路是:一个样本在特征空间中k个靠的最近的样本中,大多数 ...

  6. node jade模板数据库操作

    /* Navicat MySQL Data Transfer Source Server         : localhost Source Server Version : 50519 Sourc ...

  7. Linux下端口映射工具rinetd

    Linux下简单好用的工具rinetd,实现端口映射/转发/重定向官网地址http://www.boutell.com/rinetd 软件下载wget http://www.boutell.com/r ...

  8. 获400 万美元 A 轮融资,ShipBob 想帮助小微企业享受Amazon Prime 级配送服务 2016-06-18

    Weiss认为,无论零售市场的发展走向如何波动,ShipBob公司都能够获得坚实的成长表现. 在线销售实体商品的小型企业当然希望利用种种方式取悦客户,但面对着Amazon Prime迅如闪电且价格实惠 ...

  9. VirtualBox安装及Linux基本操作(操作系统实验一)

    VirtualBox安装教程博客链接(转载)https://blog.csdn.net/u012732259/article/details/70172704 实验名称:Linux的基本操作 实验目的 ...

  10. nginx配置hls

    备注:本来是想用浏览器播放hls,后来没有成功,最后使用flash播放rtmp的方案.所以下面的配置未使用. 修改/usr/local/nginx/conf/nginx.conf文件内容如下: wor ...