[bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
题意可能会很绕
一句话:基环树的直径。
求直径:
对于环上每一个点记录其向它的子树最长路径为$dp_x$
之后记录环上边长前缀和$ns_i$
dp值为$max_{i,j}dp[i]+sum[i]+dp[j]-sum[j]$
$dp[j]-sum[j]$提出来进单调队列。
O(n)。
记得dfs改bfs。
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long lint;
const int N=1145141;
template<typename TP>inline void read(TP &kk){
TP ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
kk=ret*f;
}
int n;
struct sumireko{int to,ne,w;}e[N*2];
int he[N],ecnt;
void addline(int f,int t,int w)
{
e[++ecnt].to=t;
e[ecnt].w=w;
e[ecnt].ne=he[f];
he[f]=ecnt;
}
bool vv[N],onr[N];
int rnd[N*2],hp,sp,nw[N*2];
lint ns[N*2]; int find(int x,int f)
{
if(vv[x]){sp=x;return 1;}
vv[x]=1;int tmp;
for(int i=he[x],t;i;i=e[i].ne)
{
t=e[i].to;
if(i==((f&1)?f+1:f-1)) continue;
if(tmp=find(t,i))
{
if(tmp==1)
{
rnd[++hp]=x;
onr[x]=1;
nw[hp]=e[i].w;
if(x!=sp) return 1;
}
return 2;
}
}
return 0;
}
lint dp[N],ans0,ans1;
int h,l;
int st[N];
bool use[N];
int fa[N];
void bfs(int u)
{
h = 1,l = 0;
st[++l] = u;
use[u]=1;
while(h<=l)
{
u = st[h++];
for(int j=he[u];j;j=e[j].ne)
{
int to = e[j].to;
if(use[to]||onr[to])continue;
use[to] = 1;
fa[to] = u;
st[++l] = to;
}
}
for(int i=l;i>=1;i--)
{
u = st[i];
for(int j=he[u];j;j=e[j].ne)
{
int to = e[j].to;
if(onr[to]||to==fa[u])continue;
lint tmp = dp[to]+e[j].w;
ans0 = max(ans0,dp[u]+tmp);
dp[u]=max(dp[u],tmp);
}
}
}
lint ans;
int qu[N*2],qh,qt;
void fuck(int xx)
{
ans0=ans1=0;
hp=0;
find(xx,0);
int x;
for(int i=1;i<=hp;i++)
{
x=rnd[i];
bfs(x);
nw[i+hp]=nw[i];
rnd[i+hp]=rnd[i];
}
for(int i=1;i<=2*hp;i++) ns[i]=ns[i-1]+nw[i];
qh=1,qt=0;
for(int i=1;i<2*hp;i++)
{
while(qh<qt&&qu[qh]+hp<=i) qh++;
if(qh<=qt)ans1=max(ans1,dp[rnd[i]]+ns[i]+dp[rnd[qu[qh]]]-ns[qu[qh]]);
while(qh<=qt&&dp[rnd[qu[qt]]]-ns[qu[qt]]<=dp[rnd[i]]-ns[i]) qt--;
qu[++qt]=i;
}
ans+=max(ans0,ans1);
hp=0;
} int xi,yi,wi;
signed main()
{
read(n);
for(int i=1;i<=n;i++)
{
read(xi),read(wi);
addline(i,xi,wi),addline(xi,i,wi);
}
for(int i=1;i<=n;i++) if(!use[i]) fuck(i);
printf("%lld\n",ans);
return 0;
}
[bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)的更多相关文章
- BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- 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< ...
- BZOJ 1791: [IOI2008]Island 岛屿 - 基环树
传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- P4381 [IOI2008]Island(基环树+单调队列优化dp)
P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...
随机推荐
- 「codeforces - 1284G」Seollal
给定 \(n\times m\) 的网格图,有些格子有障碍,无障碍且相邻的格子之间连边形成图.保证 \((1, 1)\) 无障碍,保证无障碍格子连通. 将网格图黑白染色,相邻格子颜色不同,\((1, ...
- [LeetCode]4.寻找两个正序数组的中位数(Java)
原题地址: median-of-two-sorted-arrays 题目描述: 示例 1: 输入:nums1 = [1,3], nums2 = [2] 输出:2.00000 解释:合并数组 = [1, ...
- 五、MyBatis缓存初体验
缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存, 我们可以避免频繁的与数据库进行交互, 进而提高响应速度. 一级缓存初体验(session,默认打开) 同一查询执行两次以上:selec ...
- C# 提取Word中插入的多媒体文件(视频、音频)
在Word中可将文件通过OLE对象嵌入的方式插入到文档,包括Word.excel.PDF.PPT.图片.宏文件.文件包等在内的多种文件类型.对文档中已插入的文档对象,也可通过本文中的方法提取出来另存到 ...
- 单片机中volatile的应用
01.简述 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使 ...
- Smartbi:利用好excel分析工具,数据分析都是小case!
数据分析听起来好像很高端的样子,但是实际上在一些IT高手的眼里,只需要掌握以下几个excel数据分析小工具的使用,你也能够成为别人眼中的数据大神! 1.excel数据分析工具--条件格式 快速找出符合 ...
- 【C# 线程】ContextBoundObject类 --上下文绑定 和SynchronizationAttribute属性 、同步域
NET上下文的概念 应用程序域是进程中承载程序集的逻辑分区,在应用程序域当中,存在更细粒度的用于承载.NET对象的实体,上下文是用来确定对象的逻辑归属,那就.NET上下文Context.所有的.NET ...
- md5非对称密钥
一.MD5加密概述 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 13 ...
- c#修改密码后实现重新登录
C#中密码修改成功后,提示"密码修改成功,请重新登录.当用户一点确定的时候就跳到登录界面 直接重启程序就是了,在弹出个Messages.show("密码修改成功,请重新登录.&qu ...
- Bert不完全手册1. 推理太慢?模型蒸馏
模型蒸馏的目标主要用于模型的线上部署,解决Bert太大,推理太慢的问题.因此用一个小模型去逼近大模型的效果,实现的方式一般是Teacher-Stuent框架,先用大模型(Teacher)去对样本进行拟 ...