BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题。
首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和。
所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑一遍树的直径(这里采用DP形式,可以顺便求出最大深度,注意DP树的直径方法。。就是考虑跨过每个点的链。。见lyd书树的直径一章)。
然后就变成了环上每个点有权值,求最大价值。`````
基环树上的环处理起来方法比较多,这里由于是DP,采用断环成链的方法,把环复制两遍,然后对第二份进行DP,就可以转化为1D1DDP,然后显然就可以单调队列优化了。
bzoj栈没开大,所以要手写递归栈或者用其他方法。。不想写了,所以直接在luogu交了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e6+;
struct thxorz{
int head[N],nxt[N<<],to[N<<],w[N<<],tot;
thxorz(){tot=;}
inline void add(int x,int y,int z){
to[++tot]=y,nxt[tot]=head[x],head[x]=tot,w[tot]=z;
to[++tot]=x,nxt[tot]=head[y],head[y]=tot,w[tot]=z;
}
}G;
int n,m;
#define y G.to[j]
int vis[N],lp[N<<],q[N],l,r,lpfa,cir,flag;
ll d[N],sum[N<<],ans,res;
void dfs(int x,int fa){//dbg(x);
vis[x]=;
for(register int j=G.head[x];j&&!flag;j=G.nxt[j])if(j^(fa^)){//dbg(y);
if(!vis[y]){
dfs(y,j);
if(flag)lp[++m]=x,sum[m]=sum[m-]+G.w[j];
}
else return lpfa=y,lp[m=]=x,sum[]=G.w[j],flag=,void();
}
if(!flag)vis[x]=;
if(x==lpfa)flag=;
}
void dp(int x){//dbg(x);
vis[x]=;
for(register int j=G.head[x];j;j=G.nxt[j])if(!vis[y])
dp(y),MAX(ans,d[y]+d[x]+G.w[j]),MAX(d[x],d[y]+G.w[j]);
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n);
for(register int i=,y,z;i<=n;++i)read(y),read(z),G.add(i,y,z);
for(register int i=;i<=n;++i)if(!vis[i]){
l=,r=ans=m=;dfs(i,);//dbg2("ok loop",m);
for(register int j=;j<=m;++j)dp(lp[j]);//dbg2("ok tree",lp[j]);
for(register int j=;j<=m;++j){
while(l<=r&&d[lp[j]]-sum[j]>=d[lp[q[r]]]-sum[q[r]])--r;
q[++r]=j;
}
for(register int j=m+;j<=m<<;++j){
while(l<=r&&q[l]<=j-m)++l;
sum[j]=sum[m]+sum[j-m],lp[j]=lp[j-m];
MAX(ans,d[lp[q[l]]]+d[lp[j]]+sum[j]-sum[q[l]]);
while(l<=r&&d[lp[q[r]]]-sum[q[r]]<=d[lp[j]]-sum[j])--r;
q[++r]=j;
}
res+=ans;
}
printf("%lld\n",res);
return ;
}
总结:环上问题多有断环成链做法。
BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]的更多相关文章
- P4381 [IOI2008]Island(基环树+单调队列优化dp)
P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】
我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- BZOJ 1791: [IOI2008]Island 岛屿 - 基环树
传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- BZOJ1791: [Ioi2008]Island 岛屿
BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【bzoj3831】[Poi2014]Little Bird 单调队列优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6826475.html 题目描述 In the Byteotian Line Forest there are t ...
随机推荐
- Java入门请不要放弃,学习路线以及侧重点分析
前言: ●众多的语言,到底哪一门才是适合我的? ●我们为什么要学习Java语言呢? ●Java学习路线 我们可以通过今年最新的TIOBE编程语言排行榜看到,JAVA在"昨天".和& ...
- 运行servlet跳转页面变成了下载界面,或者中文乱码
1.是这个地方的问题,敲错了Setvlet不能识别HTML文件,所以变成了下载.2.这个也是防止中文乱码 //设置响应内容类型response.setContentType("text/ht ...
- Eureka 服务中心
old 使用Eure ...
- PostgreSQL练习3
select dname,count(ename),avg(sal),sum(sal) from emp e,dept d where e.deptno=d.deptno group by dname ...
- Python中几个必须知道的函数
Python中自带了几个比较有意思的函数,一般在面试或者笔试基础的时候会问到,其中3个就是map.filter.reduce函数. 1.map(function, iterable) 它第一个要传的元 ...
- 把.exe的格式的运行程序加到电脑本地服务的办法(本文来源于百度)
Instsrv.exe(可以给系统安装和删除服务) Srvany.exe(可以让程序以服务的方式运行) 方法/步骤 要实现这个功能要用到微软提供的两个小工具“instsrv.exe”和“srv ...
- Python 常用内置模块详解
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...
- javascript 的惯性运动
移动端的惯性运动,最早来自 ios 的专利.用于手指滑动,离开屏幕之后,屏幕内容继续滚动.更有动态感. 这里,以 pc 端,鼠标横向(沿x轴) 拖拽的,惯性计算.移动端同理 具体代码如下: <! ...
- C++反汇编第四讲,认识多重继承,菱形继承的内存结构,以及反汇编中的表现形式.
目录: 1.多重继承在内存中的表现形式 多重继承在汇编中的表现形式 2.菱形继承 普通的菱形继承 虚继承 汇编中的表现形式 一丶多重继承在内存中的表现形式 高级代码: class Father1 { ...
- SMTP实现发送邮箱1
#include "stdafx.h" #include <iostream> #include <WinSock2.h> using namespace ...