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 ...
随机推荐
- 第24课.经典问题解析(1.析构函数的顺序;2.const修饰对象;3.成员函数,成员变量是否属于具体对象)
1.当程序中存在多个对象的时候,如何确定这些对象的析构顺序? 单个对象 单个对象创建时构造函数的调用顺序 a.调用父类的构造函数 b.调用成员变量的构造函数(调用顺序与声明顺序相同) c.调用类自身的 ...
- eNSP——通过Telent登录系统
我们先介绍一下Telent是干啥的: Telnet通常用在远程登录应用中,以便对本地或远端运行的网络设备进行配置.监控和维护.如网络中有多台设备需要配置和管理,用户无需为每一台 设备都连接一一个用户终 ...
- jq+js获取到table标签中的value
前端jsp页面,(这里接收后端的参数方式没有放在上面) <table> <tbody id="fPzQwQwzbrList"> <tr id=&quo ...
- vue中的axios.post使用json数据传输,出现请求头字段内容类型是不被允许的情况的解决方案
如何解决出现AXIOS的Request header field Content-Type is not allowed by Access-Control-Allow-Headers in pref ...
- jQuery实现form表单序列化转换为json对象功能示例
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- 解决Eclipse中文文档注释错位-处女座的悲哀!
1.右键打开eclips属性 2.选择兼容性为win8,然后打开Eclipse即可解决 作者:醉烟 出处:https://www.cnblogs.com/WangLei2018/ 本文版权归作者 ...
- 【Jmeter源码解读】002——程序入口类NewDriver.java
1.运行环境的检查 2.刚才初始化的 classloader 加载类 org.apache.jmeter.JMeter 然后通过 java 反射的方式来调用 org.apache.jmeter.JMe ...
- 剑指offer47:位运算+递归。求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
1 题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 2 思路和方法 (1)递归,不能使用if等 ...
- Pots(POJ-3414)【BFS】
题意:有两个有着固定容量的茶壶,初始时都为空,要求用FILL,POUR,DROP三种操作来准确地得到C值,输出最少次数及操作方案. 思路:比赛的时候真是脑子不好使,根本没想到是搜索,看了别人的题解用搜 ...
- C++11 bind和function用法
function是一个template,定义于头文件functional中.通过function<int(int, int)> 声明一个function类型,它是“接受两个int参数.返回 ...