【NOI2013】快餐店

链接:http://uoj.ac/problem/126

YY了一个线段树+类旋转卡壳的算法。骗了55分。还比不上$O(n^2)$暴力T^T

题目实际上是要找一条链的两个端点,链的中点处建快餐店。要求这两个端点的最短距离为其他所有点对的最短距离的最大值。

  1. 这条链不经过环,那答案就是环上挂的某个子树的子树直径。至少大于等于最大的树直径。树DP一发得到Ans1
  2. 经过环,显然不会饶环一圈。这个链必定由这样构成:x,y为环上两点。x子树最长链->x-y最短路-y子树最长链。可以枚举断掉一条边,然后求树的直径。取min。

第二种情况具体做法:枚举环上的边i-i+1。

$定义S_U(x)表示S_U(x)+sum[x]为到1的最长链,$

$P_U(x)表示P_U+sum[n]-sum[x]为到1的最长链即环的另一侧。$

$ S_V(x)表示前缀到x的最长链+x子树最长链,P_V(x)表示后缀的。sum[i]为环上前i条边的边权和$

  直径$=max\{S_U(i)+P_U(i+1)+sum[n]-当前该边边权,S_v(i),P_V(i+1)\}$ Ans2=min{Ans2,直径}

$Ans=\frac{max\{Ans1,Ans2\}}{2.0}.$

然后有一些细节,建议自己画画图分析下。

#include<cstdio>
#include<algorithm> typedef long long ll;
template
inline void read(T&x)
{
x=0;bool f=0;char c=getchar();
while((c<'0'||c>'9')&&c!='-')c=getchar(); if(c=='-')f=1,c=getchar();
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x=f?-x:x;
} const int MAXN(100010),LEN(200010);
const ll INF(0x7fffffffffffffff);
int n,a[MAXN],b[MAXN],l[MAXN];
struct Node{int nd,nx,co;}bot[MAXN<<1];int tot,first[MAXN];
void add(int a,int b,int c){bot[++tot]=(Node){b,first[a],c};first[a]=tot;}
int st[MAXN],pos[MAXN],last[MAXN],tp;bool bf[MAXN],vis[MAXN];
int Ring[LEN],dis[LEN],Rsize;
void DFS(int x,int f)
{
st[++tp]=x;pos[x]=tp;
for(int v=first[x];v;v=bot[v].nx)
if(bot[v].nd!=f)
{
if(pos[bot[v].nd])
{
if(dis[1])continue;
for(int i=pos[bot[v].nd];i<=tp;i++)
{
Ring[++Rsize]=st[i];bf[st[i]]=1;
dis[Rsize]=last[st[i]];
}
dis[1]=bot[v].co;
}else
{
last[bot[v].nd]=bot[v].co;
DFS(bot[v].nd,x);
}
}
--tp;pos[x]=0;
}
void umax(ll &a,ll b){if(a<b)a=b;}
ll max(ll a,ll b){return a>b?a:b;}
ll min(ll a,ll b){return a<b?a:b;}
ll lm[MAXN],Ans,Ans2,all;
void DP(int x)
{
bf[x]=1;
for(int v=first[x];v;v=bot[v].nx)
if(!bf[bot[v].nd])
{
DP(bot[v].nd);
umax(Ans,lm[x]+lm[bot[v].nd]+bot[v].co);
umax(lm[x],lm[bot[v].nd]+bot[v].co);
}
}
ll Sv[MAXN],Su[MAXN],Pv[MAXN],Pu[MAXN],Sd[MAXN],Pd[MAXN];
void Get_Ring()
{
Ring[Rsize+1]=Ring[1];dis[Rsize+1]=dis[1];
for(int i=1;i<=Rsize;i++)
{
Sv[i]=(i!=1)?Sd[i-1]+dis[i]+lm[Ring[i]]:lm[Ring[i]];
umax(Sv[i],Sv[i-1]);
Sd[i]=(i!=1)?max(Sd[i-1]+dis[i],lm[Ring[i]]):lm[Ring[i]];
Su[i]=max(Su[i-1]-dis[i],lm[Ring[i]]);
all+=dis[i];
}
for(int i=Rsize+1;i>1;i--)
{
Pv[i]=(i!=Rsize+1)?Pd[i+1]+dis[i+1]+lm[Ring[i]]:lm[Ring[i]];
umax(Pv[i],Pv[i+1]);
Pd[i]=(i!=Rsize+1)?max(Pd[i+1]+dis[i+1],lm[Ring[i]]):lm[Ring[i]];
if(i!=Rsize+1)Pu[i]=max(Pu[i+1]-dis[i+1],lm[Ring[i]]);
//以防lm[Ring[1]]被加两次
}
Ans2=INF;
for(int i=1;i<=Rsize;i++)
Ans2=min(Ans2,max(max(Sv[i],Pv[i+1]),Su[i]+Pu[i+1]+all-dis[i+1]));
}
int main()
{
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
read(n);
for(int i=1;i<=n;i++)
{
read(a[i]),read(b[i]),read(l[i]);
add(a[i],b[i],l[i]),add(b[i],a[i],l[i]);
}
DFS(1,0);
for(int i=1;i<=n;i++)if(bf[i])DP(i);
Get_Ring();
umax(Ans,Ans2);
printf("%.1lf",(Ans+0.05)/2.0);
return 0;
}
 

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. 【BZOJ3242】【UOJ#126】【NOI2013】快餐店

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

  5. UOJ #126 【NOI2013】 快餐店

    题目链接:快餐店 震惊!某ZZ选手此题调了一天竟是因为……>>点击查看 一般碰到这种基环树的题都要先想想树上怎么做.这道题如果是在树上的话……好像求一遍直径就做完了?答案就是直径长度的一半 ...

  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. .net core webapi +ddd(领域驱动)+nlog配置+swagger配置 学习笔记(2)

    DDD领域驱动模型设计 什么是DDD 软件开发不是一蹴而就的事情,我们不可能在不了解产品(或行业领域)的前提下进行软件开发,在开发前,通常需要进行大量的业务知识梳理,而后到达软件设计的层面,最后才是开 ...

  2. InnoDB信息说明

    InnoDB是MySQL数据库发展至今一款至关重要的数据库存储引擎,其不仅支持事务特性,并且具有丰富的统计信息,便于数据库管理人员了解最近InnoDB存储引擎的运行状态. 早期版本的InnoDB存储引 ...

  3. Mail.Ru Cup 2018 Round 2C(__gcd)

    #include<bits/stdc++.h>using namespace std;long long mx(long long l1,long long r1,long long l2 ...

  4. nginx 服务器并发优化

    apache 提供的 ab 可以对服务器进行压力测试, 安装 ab:   apt-get install apache2-utils 安装完后,ab 在目录  /usr/bin/ 下的. 执行: ab ...

  5. k8s 更新应用程序

    参考:https://kubernetes.io/docs/tutorials/kubernetes-basics/ 更新应用程序 用户希望应用程序始终可用,开发人员每天需要部署几次新版本的应用程序. ...

  6. 学习:数学----gcd及扩展gcd

    gcd及扩展gcd可以用来求两个数的最大公因数,扩展gcd甚至可以用来求一次不定方程ax+by=c的解   辗转相除法与gcd 假设有两个数a与b,现在要求a与b的最大公因数,我们可以设 a=b*q+ ...

  7. Luogu P2290 [HNOI2004]树的计数 Prufer序列+组合数

    最近碰了$prufer$ 序列和组合数..于是老师留了一道题:P2624 [HNOI2008]明明的烦恼 qwq要用高精... 于是我们有了弱化版:P2290 [HNOI2004]树的计数(考一样的可 ...

  8. win10系统添加照片查看器(win7版)

    很多人不习惯win10的照片查看器,还是比较怀念win7版本的照片查看器,通过以下两种方法可以在win10图片上点击右键时,"打开方式"中重现"Windows照片查看器& ...

  9. (转)CentOS 6下配置软RAID图文详解

    CentOS 6下配置软RAID图文详解 原文:http://blog.51cto.com/hujiangtao/1929620 一.RAID 简介 RAID 是英文Redundant Array o ...

  10. Linux系统的vim编辑器的配置文件的初步说明

    vim 编辑器的基本说明 vi编辑器的功能类似于Windows下的记事本,只能编辑普通文本,而vim编辑器则相当于Windows下的notepad++等高级编辑器,提升了代码开发效率. 将vi命令默认 ...