【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座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- 网络拓扑自动发掘之三层设备惯用的SNMP OID的含义
原文地址:https://blog.csdn.net/maty_wang/article/details/81305070 1. ipNetToMediaIfIndex Name/OID: ipNet ...
- 001-电脑操作规范-2019年03月.doc
001-电脑操作规范-2019年03月.doc 本文作者:徐晓亮 BoAi 作者腾讯QQ号码:595076941 /////////////////////////////////////// ...
- Python-类的绑定方法与非绑定方法
类中定义的函数分成两大类 一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入): 绑定到类的方法:用classmethod装饰器装饰的方法. 为类量身定制 类.boud_method() ...
- Python_架构、同一台电脑上两个py文件通信、两台电脑如何通信、几十台电脑如何通信、更多电脑之间的通信、库、端口号
1.架构 C/S架构(鼻祖) C:client 客户端 S:server 服务器 早期使用的一种架构,目前的各种app使用的就是这种架构,它的表现形式就是拥有专门的app. B/S架构(隶属于C/ ...
- 非常详细的Docker学习教程
一.Docker 简介 Docker 两个主要部件: Docker: 开源的容器虚拟化平台 Docker Hub: 用于分享.管理 Docker 容器的 Docker SaaS 平台 -- Docke ...
- oracle一些单记录函数
单记录函数 1.0 NVL() 作用:从两个表达式返回一个非NULL值 用法:NVL(表达式1, 表达式2) 如果表达式1的结果不为NULL,返回表达式1的结果:如果表达式1的结果为NULL,返回表达 ...
- 学习笔记:filter_var()函数
PHP 过滤器用于对来自非安全来源的数据(比如用户输入)进行验证和过滤 filter_var() 函数通过指定的过滤器过滤变量. 如果成功,则返回已过滤的数据,如果失败,则返回 false. 语法 f ...
- Auzre系列1.1.1 —— 安装用于 IntelliJ 的 Azure 工具包
(文中大部分内容(95%)Azure官网上有,我只是把我自己实际操作中遇到的问题在这里阐述一下.) 先决条件 若要完成文章中的步骤,需要安装用于 IntelliJ 的 Azure 工具包,该工具包需要 ...
- Map接口----Map中嵌套Map
package cn.good.com; import java.util.HashMap; import java.util.Iterator; import java.util.Map; impo ...
- java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=fun2], {ExactMatcher:fDisplayName=fun2(cn.itcast.demo2.fun1)], {LeadingIdentifierMatcher:fClassName=cn.itcast.demo2.fun1,fLeadi
Junit报的错误, 在测试方法前面没有添加注解@Test