基环树直径裸题。

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

所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑一遍树的直径(这里采用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. 使用C++11原子量实现自旋锁

    一.自旋锁 自旋锁是一种基础的同步原语,用于保障对共享数据的互斥访问.与互斥锁的相比,在获取锁失败的时候不会使得线程阻塞而是一直自旋尝试获取锁.当线程等待自旋锁的时候,CPU不能做其他事情,而是一直处 ...

  2. Mysql性能优化之---(一)

    mysql的性能优化无法一蹴而就,必须一步一步慢慢来,从各个方面进行优化,最终性能就会有大的提升. Mysql数据库的优化技术 对mysql优化是一个综合性的技术,主要包括 表的设计合理化(符合3NF ...

  3. php-fpm的参数优化

    查看php-fpm的内存占用 1.查看php-fpm的进程个数 ps -ef |grep "php-fpm"|grep "pool"|wc -l 2.查看每个p ...

  4. [Agc028A]Two Abbreviations_数学

    Two Abbreviations 题目链接:https://atcoder.jp/contests/agc028/tasks/agc028_a 数据范围:略. 题解: 题目中的位置非常不利于思考,我 ...

  5. Javascript性能优化阅读笔记

    第一章 加载和执行 大多数浏览器都是用单一进程处理UI界面的刷新和JavaScript的脚本执行,所以同一时间只能做一件事,Javascript执行过程耗时越久,浏览器等待响应的时间就越长. 所以,H ...

  6. Java安全停止线程方法

    1. 早期Java提供java.lang.Thread类型包含了一些列的方法 start(), stop(), stop(Throwable) and suspend(), destroy() and ...

  7. 如何创建一个前端 React 组件并发布到 NPM

    首先npm文档摆在这里: https://www.npmjs.cn/ 参考组件 https://github.com/rakuten-rex/rex-dropdownhttps://www.npmjs ...

  8. RabbitMQ的特点与应用场景(二)

      1.RabbitMQ的主要特点 (1)可靠性:RabbitMQ可通过队列持久化,交换机持久化,消息持久化及ACK回应等机制保证可靠性 (2)支持多种语言与协议:RabbitMQ几乎支持所有的编程语 ...

  9. C#面向对象(抽象类、接口、构造函数、重载、静态方法和静态成员)

    1.抽象类    抽象类关键词   abstract   (抽象)  override    (重写) 在父集中用   abstract 表示抽象类,抽象方法,在子集中用  override 改写 抽 ...

  10. 记录lucene.net的使用过程

    之前公司要做一个信息展示的网站,领导说要用lucene.net来实现全文检索,类似百度的搜索功能,但是本人技术有限,只是基本实现搜索和高亮功能,特此记录: 先看下页面效果,首先我搜索“为什么APP消息 ...