BZOJ3242 快餐店
题意
给定一个n条边n个点的连通图,求该图的某一点在该图距离最远的点距离它的距离的最小值。
题解
显然,答案是\(\frac {原图直径}{2}\)。
本体的图有 \(n\) 个点 \(n\) 条边,很显然是基环树。
那么拆掉任意一条环上的边,该图就会变为一颗普通树。
随意选择一条环上的边断开,设一端为 \(s\),一端为 \(t\), 长度为 \(len\)。
分类讨论一下该图的直径经过环和断边的情况:
1、直径经过断开的边;
2、直径不经过断开的边,经过环;
3、直径不经过环。
显然,若直径经过断开的边,就需要得出环上每个点的字数距离 \(s\) 最远点距离 \(s\) 的值,此值很显然可以在环上跑一边 \(DP\) 求出;
若直径不经过断开的边,则需要得出环上某两个点的子树的最远点之间的距离的最大值,此值仍然可以在环上跑一边 \(DP\) 求出。
故我们可以从 \(s\) 点开始,\(O(n)\) 从两个方向扫两遍环,在扫环的过程中,求出直径不经过环的情况的答案,同时维护两个 \(DP\) 值:
1、经过的环上的点的子树中,距离 \(s\) 最远的点距离 \(s\) 的值,定义该值为 \(u_1\)(正向)和 \(u_2\)(反向);
2、在经过的环上的点中,某两个距离最远的子树的最远点之间的距离,定义该值为 \(v_1\)(正向)和 \(v_2\)(反向);
扫描结束后,再遍历一遍环上的点更新答案值。
\(DP\) 方程:
\(ans = min(ans, max (max (v_1[i], v_2[i + 1]), u_1[i] + u_2[i + 1] + len))\)
注意更新结束后,还需要与直径不经过环的情况求一下最值。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5;
int n, sum, mx, cirsum, ans, ans1, tim, lstlen, f[N], u1[N], u2[N], v1[N], v2[N], fa[N], fal[N], tims[N], oncir[N], cirnum[N], cirlen[N];
vector <pair <int, int> > v[N];
void make_cir (int s, int t) {
int now = s;
while (now != t) {
oncir[now] = 1;
cirnum[++ cirsum] = now;
cirlen[cirsum] = fal[now];
now = fa[now];
}
return ;
}
void dfs (int x) {
tims[x] = ++ tim;
for (int i = 0; i < v[x].size (); i ++) {
int y = v[x][i].first;
if (tims[y] && tims[y] > tims[x]) {
make_cir (y, x);
oncir[x] = 1;
cirnum[++ cirsum] = x;
cirlen[cirsum] = v[x][i].second;
} else if (!tims[y]) {
fa[y] = x;
fal[y] = v[x][i].second;
dfs (y);
}
}
return ;
}
void dfs2 (int x, int lst) {
for (int i = 0; i < v[x].size(); i ++) {
int y = v[x][i].first, w = v[x][i].second;
if (y == lst || oncir[y])
continue ;
dfs2 (y, x);
ans = max (ans, f[x] + f[y] + w);
f[x] = max (f[x], f[y] + w);
}
return ;
}
signed main () {
scanf ("%lld", &n);
for (int i = 1; i <= n; i ++) {
int uu, vv, ww;
scanf ("%lld%lld%lld", &uu, &vv, &ww);
v[uu].push_back (make_pair (vv, ww));
v[vv].push_back (make_pair (uu, ww));
}
dfs (1);
for (int i = 1; i <= cirsum; i ++)
dfs2 (cirnum[i], 0);
for (int i = 1; i <= cirsum; i ++) {
sum += cirlen[i - 1];
u1[i] = max (u1[i - 1], f[cirnum[i]] + sum);
v1[i] = max (v1[i - 1], f[cirnum[i]] + mx + sum);
mx = max (mx, f[cirnum[i]] - sum);
}
lstlen = cirlen[cirsum];
cirlen[cirsum] = 0;
sum = 0;
mx = 0;
for (int i = cirsum; i >= 1; i --) {
sum += cirlen[i];
u2[i] = max (u2[i + 1], f[cirnum[i]] + sum);
v2[i] = max (v2[i + 1], f[cirnum[i]] + mx + sum);
mx = max (mx, f[cirnum[i]] - sum);
}
ans1 = v1[cirsum];
for (int i = 1; i < cirsum; i ++)
ans1 = min (ans1, max (max (v1[i], v2[i + 1]), u1[i] + u2[i + 1] + lstlen));
ans = max (ans, ans1);
printf ("%.1lf\n", (double)(ans / 2));
return 0;
}
本博客思路参考自 https://blog.csdn.net/zlttttt/article/details/73149529
BZOJ3242 快餐店的更多相关文章
- 【BZOJ3242】【NOI2013】快餐店(动态规划)
[BZOJ3242][NOI2013]快餐店(动态规划) 题面 BZOJ 题解 假设我们要做的是一棵树,那么答案显然是树的直径的一半. 证明? 假设树的直径是\(2d\),那么此时最远点的距离是\(d ...
- 【BZOJ3242】【UOJ#126】【NOI2013】快餐店
NOI都是这种难度的题怎么玩嘛QAQ 原题: 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. ...
- BZOJ3242 [Noi2013]快餐店 【环套树 + 单调队列dp】
题目链接 BZOJ3242 题解 题意很清楚,找一点使得最远点最近 如果是一棵树,就是直径中点 现在套上了一个环,我们把环单独拿出来 先求出环上每个点外向树直径更新答案,并同时求出环上每个点外向的最远 ...
- BZOJ3242/UOJ126 [Noi2013]快餐店
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- bzoj3242 [Noi2013]快餐店
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 3242: [Noi2013]快餐店 - BZOJ
Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城 ...
- 快餐店运行模拟C++程序源码代写
某快餐店供应若干种快餐和饮料(5种以上),早晨6:00开始营业,晚上11:00打烊.前一天已经安排了若干工人上班,快餐店的用餐位是固定的,每种食物的成本和销售价格是确定的,每种食物的总量是确定的,储存 ...
- 从医生看病和快餐店点餐理解Node.js的事件驱动
第一个例子是关于医生看病. 在美国去看医生,需要填写大量表格,比如保险.个人信息之类,传统的基于线程的系统(thread-based system),接待员叫到你,你需要在前台填写完成这些表格,你站着 ...
- bzoj 3242: [Noi2013]快餐店 章鱼图
3242: [Noi2013]快餐店 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 266 Solved: 140[Submit][Status] ...
随机推荐
- 第三届蓝桥杯JavaC组国(决)赛真题
解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1. 填算式 [结果填空] (满分11分) 看这个算式: ☆☆☆ + ☆☆☆ = ☆☆☆ 如果每个五角星代表 1 ~ 9 的不同的数字. ...
- Java实现 蓝桥杯 历届试题 数字游戏
问题描述 栋栋正在和同学们玩一个数字游戏. 游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈.栋栋首先说出数字1.接下来,坐在栋栋左手边的同学要说下一个数字2.再下面的一个同学要从上一个同学说的数 ...
- java实现第六届蓝桥杯打印大X
打印大X 打印大X 小明希望用星号拼凑,打印出一个大X,他要求能够控制笔画的宽度和整个字的高度. 为了便于比对空格,所有的空白位置都以句点符来代替. 要求输入两个整数m n,表示笔的宽度,X的高度.用 ...
- python3 基本书写规范
一.缩进在类.函数定义完成后需要接着写子代码快需要在定义完成后加上: 缩进格式为首字母开始空格4个位置(取消了大括号以冒号代替子模块)例: class pop: #类的定义方式 def pip: #函 ...
- 几种常见的dfs模板
判断从v出发是否能走到终点 bool dfs(v){ if(v is 终点)return true; if(v is 旧点)return false; 将v标记为旧点: 对和v相邻的每个节点u{ if ...
- 基于Azure IoT开发.NET物联网应用系列-全新的Azure IoT架构
物联网技术已经火了很多年了,业界各大厂商都有各自成熟的解决方案.我们公司主要搞新能源汽车充电,充电桩就是物联网技术的最大应用,车联网.物联网.互联网三网合一.2017年的时候重点研究过Azure Io ...
- jsp页面用DBHelper实现简单的登陆验证
首先我们需要写一个简单的登陆页面login.jsp,然后用from表单提交给index.jsp页面.在index.jsp页面通过DBHelper连接数据库判断账号和密码,如果密码正确则显示登陆成功. ...
- zabbix服务无法正常启动
环境介绍 操作系统 centos 7.4 zabbix 3.4.7 故障现象说明 zabbix agent无法启动 web 监控不到客户端服务器 查看日志报错 提示不能打开日志,不能创建信 ...
- 红楼梦 + 写入 MySQL
import requests import re import pymysql from bs4 import BeautifulSoup conn = pymysql.Connect(host=' ...
- CAT12提取surface指标
介绍 基于表面的形态学分析(VSM)的方法被越来越多的研究者使用.本文主要介绍基于SPM12和CAT12工具包进行ROI-based VSM的处理步骤. 方法 本文数据处理使用的工具是MATLAB,S ...