基环树直径裸题。

首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和。

所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑一遍树的直径(这里采用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]的更多相关文章

  1. P4381 [IOI2008]Island(基环树+单调队列优化dp)

    P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...

  2. [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)

    [bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...

  3. bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】

    我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...

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

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

  5. BZOJ 1791: [IOI2008]Island 岛屿 - 基环树

    传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...

  6. [BZOJ1791][IOI2008]Island岛屿(环套树DP)

    同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...

  7. BZOJ1791: [Ioi2008]Island 岛屿

    BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...

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

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

  9. 【bzoj3831】[Poi2014]Little Bird 单调队列优化dp

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826475.html 题目描述 In the Byteotian Line Forest there are   t ...

随机推荐

  1. Java学习笔记-内部类

    内部类在Android中有着大量的运用 内部类 内部类提供了更好的封装:内部类可以直接访问外部类的私有数据:匿名内部类适合那些只需要使用一次的类.非静态内部类不能拥有静态成员.内部类比外部类可以多使用 ...

  2. Hogan.js的使用

    一个比较简单的前端模板引擎,参考一下两篇文件即可学会:https://www.cnblogs.com/zhangruiqi/p/8547268.htmlhttps://www.imooc.com/ar ...

  3. Django之session详解

    好文章来自追风的小蚂蚁:https://www.cnblogs.com/zhuifeng-mayi/p/9099811.html cookie:Cookie,有时也用其复数形式 Cookies,指某些 ...

  4. std::unique_lock与std::lock_guard分析

    背景 C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢,导致程序出现未定义或异常行为.通常的做法是在修改共享数据成员时进行加锁(mutex).在使用锁 ...

  5. [python] 一行命令搭建http服务内网传文件

    在Linux服务器上或者Windows服务器上,只要安装python,均可以使用此命令,建立一个内网可以快速访问的WEB服务. 在想要搭建WEB服务的目录下,使用Python3.x内置方法: pyth ...

  6. Ubuntu 16.04 安装vim8

    1. 卸载旧版本vim sudo apt-get remove vim vim-runtime gvim sudo apt-get remove vim-tiny vim-common vim-gui ...

  7. 剑指offer12:求解double类型的浮点数base和int类型的整数exponent的次方。 保证base和exponent不同时为0

    1. 题目描述 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方.保证base和exponent不同时为0. 2. 思路和方法 分析: 由于 ...

  8. 网站页面顶部出现空白行&#65279字符的原因以及完美解决办法

    转自个人博客:https://www.hurbai.com 有时候网页头部会出现一个空白行,查看源码发现body开头初有一个非法字符 // 如果是Windows系统,修改为:$WIN = 1; $W ...

  9. HTNL基础之一

    HTML:超文本标记语言 <-- 最好可以自己默写出来 --> <!DOCTYPE HTML> <html> <head> <title>& ...

  10. Linux/CentOS 配置Mysql-server过程和遇到错误解决方法

    第一步:下载mysql-server 方法1.wget url(你所要下载的链接,可以从mysq官网查找)到当前目录下 方法2.到mysql官网下载包之后通过xftp传到linux 第二步:解压tar ...