题目描述

  题目很长,大家自己去看吧。

  bzoj

  vijos

  原题\(n\leq 300\)

  加强版\(n\leq 500000\)

题解

  这种东西当然要猜结论的啦,否则会比较麻烦。

结论1:如果有很多条直径,那么不管核在哪条直径上,最小偏心距都相同。

结论2 :任意一条路径的偏心距不会小于核的最小偏心距。

  这两个结论的证明方法类似。都是考虑两条路径的公共部分和非公共部分。如果最远的点到路径上的最近的点都在公共部分上,则偏心距相同。任意两条直径的非公共部分长度相同,最远的点到直径上的最近的点的距离显然大于最远的点到其他路径上的最近的点的距离(否则这条直径就不是直径了)。

  结论1告诉我们可以只考虑一条路径,结论2告诉我们可以考虑所有\(O(n^2)\)条路径而不用管这条路径是否在直径上。

  对于\(n\leq 300\),直接暴力枚举路径的两个端点,枚举任意一个点,算出所有其他点到这条路径的距离,就是(这个点到一个端点的距离\(+\)这个点到另一个端点的距离\(-\)这条路径的长度)\(\div 2\),算出最大值然后更新答案。

  算最短路用floyd

  时间复杂度:\(O(n^3)\)

  对于\(n\leq 500000\),找出其中一条直径,把这条直径拿出来,算出每个点往右距离不超过\(s\)的点是哪个,算出每个点忽略直径上左边所有点/右边所有点/左边+右边所有点的最远距离。这三部分的最大值就是一条路径的答案。然后从右往左计算答案,用单调队列维护答案:如果新加入队列的偏心距比队尾的偏心距大,可以把队尾删掉。算出所有路径的答案然后取\(\min\)就可以了。

  时间复杂度:\(O(n)\)

代码

//O(n^3)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return s;
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
int f[310][310];
int main()
{
int n,s;
scanf("%d%d",&n,&s);
memset(f,0x3f,sizeof f);
int i,x,y,z;
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
f[x][y]=f[y][x]=z;
}
for(i=1;i<=n;i++)
f[i][i]=0;
int j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
if(i!=k)
for(j=1;j<=n;j++)
if(j!=i&&j!=k)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
int ans=0x7fffffff;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(f[i][j]<=s)
{
int now=0;
for(k=1;k<=n;k++)
now=max(now,(f[k][i]+f[k][j]-f[i][j])/2);
ans=min(ans,now);
}
printf("%d\n",ans);
return 0;
}
//O(n)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return s;
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
struct graph
{
int v[1000010];
int w[1000010];
int t[1000010];
int h[500010];
int n;
graph()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,int y,int z)
{
n++;
v[n]=y;
w[n]=z;
t[n]=h[x];
h[x]=n;
}
};
graph g;
int from[500010];
int b[500010];
queue<int> q;
int d[500010];
int w[500010];
void bfs(int x)
{
memset(d,-1,sizeof d);
d[x]=0;
q.push(x);
int i;
from[x]=0;
w[x]=0;
while(!q.empty())
{
x=q.front();
q.pop();
for(i=g.h[x];i;i=g.t[i])
if(d[g.v[i]]==-1)
{
d[g.v[i]]=d[x]+g.w[i];
w[g.v[i]]=g.w[i];
from[g.v[i]]=x;
q.push(g.v[i]);
}
}
}
void dfs(int x,int fa,int dep,int &s)
{
s=max(s,dep);
int i;
for(i=g.h[x];i;i=g.t[i])
if(!b[g.v[i]]&&g.v[i]!=fa)
dfs(g.v[i],x,dep+g.w[i],s);
}
int a[500010];
int c[500010];
int f[500010];
int fl[500010];
int fr[500010];
pii q2[500010];
int head,tail;
void add(int x)
{
while(tail>=head&&q2[tail].second<=f[x])
tail--;
q2[++tail]=pii(x,f[x]);
}
void del(int x)
{
if(q2[head].first==x)
head++;
}
int main()
{
freopen("bzoj1999.in","r",stdin);
freopen("bzoj1999.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
int i,x,y,z;
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
g.add(x,y,z);
g.add(y,x,z);
}
bfs(1);
x=1;
for(i=1;i<=n;i++)
if(d[i]>d[x])
x=i;
bfs(x);
for(i=1;i<=n;i++)
if(d[i]>d[x])
x=i;
int t=0;
do
{
a[++t]=x;
c[t]=w[x];
x=from[x];
}
while(x);
for(i=1;i<=t;i++)
b[a[i]]=1;
int j;
for(i=1;i<=t;i++)
for(j=g.h[a[i]];j;j=g.t[j])
if(!b[g.v[j]])
dfs(g.v[j],0,g.w[j],f[i]);
for(i=1;i<=t;i++)
fl[i]=max(f[i],fl[i-1]+c[i-1]);
for(i=t;i>=1;i--)
fr[i]=max(f[i],fr[i+1]+c[i]);
for(i=1;i<=t;i++)
c[i]+=c[i-1];
head=1;
tail=0;
j=1;
int ans=0x7fffffff;
for(i=1;i<=t;i++)
{
add(i);
while(c[i-1]-c[j-1]>m)
{
del(j);
j++;
}
ans=min(ans,max(max(fl[j],fr[i]),q2[head].second));
}
printf("%d\n",ans);
return 0;
}

【BZOJ1999】【NOIP2007】树网的核 单调队列优化DP的更多相关文章

  1. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  2. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  3. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  4. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  5. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

  6. 【单调队列优化dp】 分组

    [单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...

  7. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

  8. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  9. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

随机推荐

  1. Really Big Numbers CodeForces - 817C (数学规律+二分)

    C. Really Big Numbers time limit per test 1 second memory limit per test 256 megabytes input standar ...

  2. debian中完全删除mysql

    参考自:http://www.jb51.net/article/50884.htm 之前实验室的人说找不到完全删除已安装的mysql-cluster的方法,我当时没在意,今天不得不删除他之前安装的my ...

  3. node.js介绍和npm的使用

    Node.js介绍 打开Nodejs英文网:https://nodejs.org/en/ 中文网:http://nodejs.cn/ 我们会发现这样一句话: 翻译成中文如下: Node.js 是一个基 ...

  4. 多线程系列之六:Producer-Consumer模式

    一,Producer-Consumer模式 Producer:生产者的意思,指的是生成数据的线程.Consumer:消费者的意思,指的是使用数据的线程当生产者和消费者以不同的线程运行时,两者之间的处理 ...

  5. Web系统大规模并发——秒杀与抢购 秒杀系统优化与预防措施

    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西.然而,从技术的角度来说,这对于Web系统是一个巨大的考验.当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要.这次我们 ...

  6. md5加密通过URL传给后台

    首先要把你要用的md5库引入 这个技术其实挺简单的,咋们直接贴上代码(这个是项目上的) sign = hex_md5("type="+type&"userId=& ...

  7. 四、Object.defineProperty总结

    Object.defineProperty() 参考:https://segmentfault.com/a/1190000007434923 定义: 方法会直接在一个对象上定义一个新属性,或者修改一个 ...

  8. [翻译]在asp.net core2.0 OpenID Connect Handler中丢失了声明(CLaims)?

    注:这是一篇翻译,来自这里.这篇文章讲述了在asp.net core2.0中使用openid connect handler的过程中解析不到你想要的claim时,你可以参考这篇文章. Missing ...

  9. Java Serializable的使用和transient关键字使用小记(转载)

    一:Serializable 1.持久化的简单介绍: “持久化”意味着对象的“生存时间”并不取决于程序是否正在执行——它存在或“生存”于程序的每一次调用之间.通过序列化一个对象,将其写入磁盘,以后在程 ...

  10. JavaList addAll removeAll

    List<String>list1=new ArrayList<>(); list1.add("a"); list1.add("b"); ...