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

NOI都是这种难度的题怎么玩嘛QAQ

原题:

小T打算在城市C开设一家外送快餐店。送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方。 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑。任意两个建筑之间至少存在一条由双向道路连接而成的路径。小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数)。 现给定城市C的地图(道路分布及其长度),请找出最佳的快餐店选址,输出其与最远的顾客之间的距离。

N<=10^5,Li<=10^9

恩题解比较好理解但是比较难想到……

首先不知道为什么答案不是图地直径/2……

然后显然答案是环上删去某边后树的直径,这个写n^2算法的时候会用到

然后dfs找出环,对环上每个点令其为根求出高度及直径

然后顺着扫一遍,每次记录前面所有环上边的和sum,当前节点子树高度和sum的和的最大值f1,(前面深度最大和次大子树的深度的和)和这两个子树根节点之间的距离的和的最大值f2

然后反过来再搞一遍搞出f3和f4

统计答案即可,注意还有跨过环上第一个点和最后一个点之间的边的情况,这个结合f1和f3就行

最后还要用环上所有点的子树直径的最大值更新ans(不知道为什么QAQ

NOI都是这种难度的题怎么玩嘛QAQ

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 int rd(){int z=0,mk=1;  char ch=getchar();
 9     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)mk=-1;  ch=getchar();}
10     while(ch>=‘0‘&&ch<=‘9‘){z=(z<<3)+(z<<1)+ch-‘0‘;  ch=getchar();}
11     return z*mk;}
12 struct edg{int nxt,y,v;}e[210000];  int lk[110000],ltp=0;
13 inline void ist(int x,int y,int z){  e[++ltp]=(edg){lk[x],y,z};  lk[x]=ltp;}
14 int n;
15 bool vstd[110000];  int stck[110000],tp=0,fthv[110000];
16 int ccd[110000],cct=0,ccv[110000];
17 ll dp[110000];
18 ll f[110000],f1[110000],f2[110000],f3[110000],f4[110000];
19 ll mxf=0;
20 bool gtcc(int x,int y){
21     stck[++tp]=x;
22     if(vstd[x]){
23         fill(vstd,vstd+1+n,false);
24         do vstd[ccd[++cct]=stck[tp]]=true,ccv[cct]=fthv[stck[tp--]];while(stck[tp]!=x);
25         return true;}
26     vstd[x]=true;
27     for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=y){
28         fthv[e[i].y]=e[i].v;
29         if(gtcc(e[i].y,x))  return true;}
30     --tp;
31     return false;}
32 void gtdp(int x,int y){
33     for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=y && !vstd[e[i].y]){
34         dp[e[i].y]=dp[x]+e[i].v,gtdp(e[i].y,x);
35         mxf=max(mxf,f[x]+f[e[i].y]+e[i].v);
36         f[x]=max(f[x],f[e[i].y]+e[i].v);}}
37 int main(){//freopen("ddd.in","r",stdin);
38     int l,r,z;  cin>>n;
39     for(int i=1;i<=n;++i)  l=rd(),r=rd(),z=rd(),ist(l,r,z),ist(r,l,z);
40     if(!gtcc(1,0))  return 0;
41     for(int i=1;i<=cct;++i)  gtdp(ccd[i],0);
42     ll bwl=0,mx=0,ans=0,tt=ccv[cct],tmp;  ccv[cct]=0;
43     for(int i=1;i<=cct;++i){
44         bwl+=ccv[i-1];
45         f1[i]=max(f1[i-1],bwl+f[ccd[i]]);
46         f2[i]=max(f2[i-1],mx+bwl+f[ccd[i]]);
47         mx=max(mx,f[ccd[i]]-bwl);}
48     bwl=mx=0;
49     for(int i=cct;i>=1;--i){
50         bwl+=ccv[i];
51         f3[i]=max(f3[i+1],bwl+f[ccd[i]]);
52         f4[i]=max(f4[i+1],mx+bwl+f[ccd[i]]);
53         mx=max(mx,f[ccd[i]]-bwl);}
54     ans=f2[cct];
55     for(int i=1;i<cct;++i){
56         tmp=max(f1[i]+f3[i+1]+tt,max(f2[i],f4[i+1]));
57         ans=min(ans,tmp);}
58     ans=max(ans,mxf);
59     printf("%.1lf\n",ans*1.0/2);
60     return 0;}

时间: 2024-10-17 03:37:34

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

3242: [Noi2013]快餐店 - BZOJ

Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑.任意两个建筑之间至少存在一条由双向道路连接而成的路径.小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数). 现给定城市C的地图(道路

[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 220000 #define inf 0x3ffffffffffffffLL typedef long long ll; int v[N],e[N],ne[N],nn,w[N]; void add(int x,int y,int z){ ne[++nn

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

3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 266  Solved: 140[Submit][Status] Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两

UOJ#126【NOI2013】快餐店

[NOI2013]快餐店 链接:http://uoj.ac/problem/126 YY了一个线段树+类旋转卡壳的算法.骗了55分.还比不上$O(n^2)$暴力T^T 题目实际上是要找一条链的两个端点,链的中点处建快餐店.要求这两个端点的最短距离为其他所有点对的最短距离的最大值. 这条链不经过环,那答案就是环上挂的某个子树的子树直径.至少大于等于最大的树直径.树DP一发得到Ans1 经过环,显然不会饶环一圈.这个链必定由这样构成:x,y为环上两点.x子树最长链->x-y最短路-y子树最长链.可以

【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/problem/3047/ 因为存在一条边,答案所在的点走向左右的城的最短路都不会经过这条边. 所以枚举这条边,剩下的用线段树维护. 线段树初始化搞了好久,忘了在外向树上做dp,树形dp时记录也错了,总之调了一天,吃枣药丸啊QwQ 时间复杂度$O(nlogn)$,听说有$O(n)$的单调队列做法,留一个坑以

bzoj3242 [Noi2013]快餐店

Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑.任意两个建筑之间至少存在一条由双向道路连接而成的路径.小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数). 现给定城市C的地图(道路

BZOJ3242 [Noi2013]快餐店/UOJ126

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连

[NOI2013]快餐店

题目描述 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑.任意两个建筑之间至少存在一条由双向道路连接而成的路径.小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数). 现给定城市C的地图(道路分布及其长度)

动态规划:NOI2013 快餐店

Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑.任意两个建筑之间至少存在一条由双向道路连接而成的路径.小T的快餐店可以开设在任一建筑 中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数). 现给定城市C的地图