[BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE。
大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
typedef long long ll;
using namespace std; const int N=;
ll ans,res,f[N],v1[N],v2[N],u1[N],u2[N];
int dfn[N],fa[N],pre[N],h[N],a[N],b[N];
int n,x,w,cnt,tim,tot,to[N<<],val[N<<],nxt[N<<],d[N];
void add(int u,int v,int w){ to[++cnt]=v; val[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt; } void dfs(int x){
dfn[x]=++tim;
For(i,x) if ((k=to[i])!=fa[x]){
if (!dfn[k]) fa[k]=x,pre[k]=val[i],dfs(k);
else if (dfn[k]>dfn[x]){
for (int t=k; t!=x; t=fa[t]) a[++tot]=t,d[t]=,b[tot]=pre[t];
a[++tot]=x; d[x]=; b[tot]=val[i];
}
}
} void Dfs(int x,int fa){
For(i,x) if ((k=to[i])!=fa && !d[k])
Dfs(k,x),ans=max(ans,f[x]+f[k]+val[i]),f[x]=max(f[x],f[k]+val[i]);
} void DP(int x){
tot=; ans=; dfs(x); ll sm=,mx=;
rep(i,,tot) Dfs(a[i],);
rep(i,,tot) d[a[i]]=;
rep(i,,tot+) u1[i]=u2[i]=v1[i]=v2[i]=;
rep(i,,tot){
sm+=b[i-]; u1[i]=max(u1[i-],f[a[i]]+sm);
v1[i]=max(v1[i-],f[a[i]]+sm+mx); mx=max(mx,f[a[i]]-sm);
ans=max(ans,v1[i]);
}
int tmp=b[tot]; sm=mx=b[tot]=;
for (int i=tot; i; i--){
sm+=b[i]; u2[i]=max(u2[i+],f[a[i]]+sm);
v2[i]=max(v2[i+],f[a[i]]+sm+mx); mx=max(mx,f[a[i]]-sm);
ans=max(ans,v2[i]);
}
rep(i,,tot-) ans=max(ans,u1[i]+u2[i+]+tmp);
res+=ans;
} int main(){
freopen("bzoj1791.in","r",stdin);
freopen("bzoj1791.out","w",stdout);
scanf("%d",&n);
rep(i,,n) scanf("%d%d",&x,&w),add(x,i,w),add(i,x,w);
rep(i,,n) if (!dfn[i]) DP(i);
printf("%lld\n",res);
return ;
}
[BZOJ1791][IOI2008]Island岛屿(环套树DP)的更多相关文章
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...
- BZOJ1791: [Ioi2008]Island 岛屿
BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...
- bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1826 Solved: 405[Submit][S ...
- bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿
http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- BZOJ 1791: [IOI2008]Island 岛屿 - 基环树
传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...
- 【BZOJ】1040: [ZJOI2008]骑士 环套树DP
[题意]给定n个人的ai和bi,表示第i个人能力值为ai且不能和bi同时选择,求能力值和最大的选择方案.n<=10^6. [算法]环套树DP(基环树) [题解]n个点n条边——基环森林(若干环套 ...
随机推荐
- 【STSRM13】绵津见
[算法]扫描线:差分+树状数组 [题意]转化模型后:求每个矩形覆盖多少点和每个点被多少矩形覆盖.n<=10^5. [题解]经典的扫描线问题(二维偏序,二维数点). 数点问题 将所有询问离线并离散 ...
- 【BZOJ】1798: [Ahoi2009]Seq 维护序列seq 线段树多标记(区间加+区间乘)
[题意]给定序列,支持区间加和区间乘,查询区间和取模.n<=10^5. [算法]线段树 [题解]线段树多重标记要考虑标记与标记之间的相互影响. 对于sum*b+a,+c直接加上即可. *c后就是 ...
- C语言二分查找
#include <stdio.h> /* 二分查找条件: 1.有序序列 2.数据在数组中 */ int baseBinarySearch(int a[],int h,int k) { ; ...
- 解决ajax chrome禁止本地浏览时加载本地其他文件的方法
在chrome快捷键右键--属性 “ --allow-file-access-from-files ”,前面用空格隔开.然后应用--确定.
- NYOJ 814 又见拦截导弹 (模拟)
题目链接 描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:它的第一发炮弹能够到达任意的高度,但是以 ...
- VueJS 轻松支持 JSX 配置
使用: babel-preset-vue-app TODO
- 不老的神器:安全扫描器Nmap渗透使用指南【转】
介绍 nmap是用来探测计算机网络上的主机和服务的一种安全扫描器.为了绘制网络拓扑图Nmap的发送特制的数据包到目标主机然后对返回数据包进行分析.Nmap是一款枚举和测试网络的强大工具. 特点 主机探 ...
- C#:Excel上传服务器后导入数据库
- deep learning 资源汇总
不定时更新..... 首先是吴老爷子在优酷的视频,可惜外音太大了:http://list.youku.com/albumlist/show?id=21508721&ascending=1&am ...
- Percona XtraDB Cluster(PXC) Mysql 集群
Percona XtraDB Cluster(PXC) ---原理介绍篇 目录 一.简介 1 二.优缺点 2 三.区别/局限性 3 四. PXC复制原理 4 五. 服务解释 5 ...