P4381 [IOI2008]Island

题意:求图中所有基环树的直径和

我们对每棵基环树分别计算答案。

首先我们先bfs找环(dfs易爆栈)

蓝后我们处理直径

直径不在环上,就在环上某点的子树上

我们对于环上每个点的子树,跑一边dp求直径即可,顺带处理子树的最深深度(环上点到子树某个叶节点的最长距离)$dis[x]$

在dfs求直径时顺带求直径的最大值(可能是整棵基环树的直径)

蓝后我们在环上跑一遍dp。

我们先破环成链(就是把长度为$n$的环转换成长$2n+1$的链)

偷个图

我们记链上前$i$个点之间边的总长(前缀和)$sum[i]$

枚举$j(1<=j<i,i-j<n)$,得

$ans=max(ans,dis[i]+sum[i]-sum[j]+dis[j])$,表示子树$i$的直径$+$子树$j$的直径+$i,j$在环上之间的距离

我们分离一下上面的式子:$(dis[i]+sum[i])+(dis[j]-sum[j])$

这不是可以单调队列维护

于是再搞个单调队列优化dp就完事辣

bzoj还是爆栈了TAT

#include<iostream>
#include<cstdio>
#include<cstring>
#define rint register int
using namespace std;
typedef long long ll;
inline ll Max(ll a,ll b){return a>b?a:b;}
void read(int &x){
char c=getchar();x=;
while(c<''||c>'') c=getchar();
while(''<=c&&c<='') x=x*+(c^),c=getchar();
}
#define N 1000005
int n,ri[N],d[N],is[N],To[N],W[N],fa[N],len,L,R,h[N];
ll ans,re,sum[N],dis[N]; bool vis[N];
int cnt,hd[N],nxt[N<<],ed[N],poi[N<<],val[N<<];
inline void adde(int x,int y,int v){
nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt;
ed[x]=cnt, poi[cnt]=y, val[cnt]=v;
}
void bfs(int x){//找环
rint p; vis[x]=;len=;
while(){
p=To[x];
if(vis[p]){
ri[++len]=p,d[len]=W[p],is[p]=;
for(;x!=p;x=fa[x])
ri[++len]=x,d[len]=W[x],is[x]=;
break;
}vis[p]=;fa[p]=x;x=p;
}
}
void dfs(int x,int Fa){//dfs求子树直径
vis[x]=;
for(int i=hd[x];i;i=nxt[i]){
int to=poi[i];
if(is[to]||to==Fa) continue;
dfs(to,x); re=Max(re,dis[x]+dis[to]+(ll)val[i]);
dis[x]=Max(dis[x],dis[to]+val[i]);
}
}
inline int Id(int x){return (x-)%len+;}
inline ll F(int x){return dis[ri[Id(x)]]-sum[x];}
void solve(){//单调队列优化,环上dp
L=;R=;
for(rint i=;i<=len*;++i){
sum[i]=sum[i-]+d[Id(i)];
while(L<=R&&i-h[L]>=len) ++L;
if(L<=R) re=Max(re,F(h[L])+dis[ri[Id(i)]]+sum[i]);
while(L<=R&&F(h[R])<=F(i)) --R;
h[++R]=i;
}
}
int main(){
read(n);
for(rint i=;i<=n;++i){
read(To[i]); read(W[i]);
adde(i,To[i],W[i]); adde(To[i],i,W[i]);
}
for(rint i=;i<=n;++i){
if(vis[i]) continue;
re=; bfs(i);
for(rint j=;j<=len;++j) dfs(ri[j],);
solve(); ans+=re;//每棵树分别处理
}printf("%lld",ans);
return ;
}

P4381 [IOI2008]Island(基环树+单调队列优化dp)的更多相关文章

  1. BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]

    基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...

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

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

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

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

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

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

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

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

  6. Codeforces 1304F1/F2 Animal Observation(单调队列优化 dp)

    easy 题目链接 & hard 题目链接 给出一张 \(n \times m\) 的矩阵,每个格子上面有一个数,你要在每行选出一个点 \((i,t)\),并覆盖左上角为 \((i,t)\), ...

  7. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  8. 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 ...

  9. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

随机推荐

  1. 10.26 配置psplkf小程序

    环境 服务器 Win Server 2008,nginx, maven, psplkf 标准的mvn工程,可以使用eclipse,导入,file-import-maven project就行, 但是我 ...

  2. openvpn-服务端配置文件

    ;local a.b.c.d port 1194 ;proto tcp proto udp ;dev tap dev tun ;dev-node MyTap ca /etc/openvpn/keys/ ...

  3. zhaoyin

    1.什么时候用到事务,单个update操作会用到事务吗? 银行转账 /**//*--使用事务--*/ use stuDB go --恢复原来的数据 --update bank set currentM ...

  4. ES代替DB建模后的维护流程架构

  5. 20165321实验一Java开发环境的熟悉-1

  6. 函数 return

    return 的作用 一.返回一个值给函数,主函数调用这个函数后能得到这个返回的值.二.结束函数,例如你运行到一个地方,虽然后面还有代码但是你不想再继续运行,这时就可以直接用 return:这条语句来 ...

  7. JAVA编程思想学习笔记7-chap19-21-斗之气7段

    1.枚举 2.内置三种注解 @Override @Deprecated @SuppressWarnings 3.元注解:用于注解其它注解 4.注解处理器:通过反射 5.创建线程的两种方式 实现Runn ...

  8. uml的几种关系总结

    UML类图几种关系的总结    在UML类图中,常见的有以下几种关系:泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregati ...

  9. aop编程之前置通知

    aop( Aspect-Oriented Programming)前置通知原理案例讲解 编程步骤: 定义接口 编写对象(被代理的对象即目标对象) 编写通知(前置通知即目标方法调用前调用) 在beans ...

  10. oracle查询数据字典的sql

    使用的sql语句如下: select t1.username 用户, t2.TABLE_NAME 表名称, t3.comments 表业务含义, t2.COLUMN_NAME 字段名称, t4.com ...