【BZOJ1999】【NOIP2007】树网的核 单调队列优化DP
题目描述
题目很长,大家自己去看吧。
原题\(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的更多相关文章
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- 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 ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【单调队列优化dp】 分组
[单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...
- [小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- c++入门之再次探讨类属性
精辟博文:https://blog.csdn.net/msdnwolaile/article/details/51923859(转载,仅供学习|!)
- JVM的常用的调优策略和垃圾回收算法及Tomcat的常用调优参数
jvm调优主要针对堆内存,堆内存分为:新生区.养老区和永久区 永久区存放的是系统jdk自身的interface和class的元数据,所以唯有新生区和养老区具有优化空间. 新生区:伊甸区和幸存者区.所有 ...
- MongoDB Redis
MongoDB Redis设置用户名密码了吗?看看shodan这款邪恶的搜索引擎吧!~ 早上看新闻的时候看到了个醒目的新闻 开源中国:MongoDB 赎金事件持续发酵,究竟是谁之过?博客园:Mon ...
- 聊一聊跨域,Vue向Django请求数据的一些问题
1.做前后端分离 前端使用Vue程序,后端使用Django配合rest-framework. 那么前端Vue通过API接口拿到数据会出现跨域的问题,JSONP只是在get中会用到的,所以这里使用cor ...
- nginx之快速查找配置文件
nginx的配置放在nginx.conf文件中,一般我们可以使用以下命令查看服务器中存在的nginx.conf文件. locate nginx.conf /usr/local/nginx/conf ...
- rem移动端适配方案
一. rem vs em 单位 定义 特点 rem font size of the root element 以根元素字体大小为基准 em font size of the element 以父元素 ...
- Day 5-3 多态与多态性
多态与多态性 鸭子类型 多态与多态性 多态:一类事物有多种形态.比如,动物有多种形态,人,狗,猪,豹子.水也有多种形态,冰,雪,水蒸气. #多态:同一类事物的多种形态 import abc class ...
- RandomStringUtils
System.out.println(RandomStringUtils.random(5));//随机多少个随机字符中文环境乱码 System.out.println(RandomStringUti ...
- Spirng boot maven多模块打包不踩坑
本文参考 https://blog.csdn.net/Ser_Bad/article/details/78433340 经过实战一次通过.回话不多说,话费不多说,直接上图. 项目整体结构: 父模块: ...
- linux audit审计(6)--audit永久生效的规则配置
定义reboot系统后,仍然生效的审计规则,有两种办法: 1.直接写入/etc/audit/audit.rules文件中,在service文件中需要加入ExecStartPost=-/sbin/aud ...