bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791
题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和。n<=1e6
题解:基环树DP写的很少……
树的直径不用解释了,就是NOIP2018D1T3的20分做法,基环树直径,我们可以yy一下然后就能发现答案是2种:1、把环剖去以后其余的子树的直径。2、环上的一部分+选中的2点中各自的最长链。
第一种可以直接dfs求解,对于第二种……我们可以摒弃垃圾的dfs两遍求树的直径的做法,改成DP形式的求树的直径。然后找到一个环时,记录环上的点最深的深度,然后可以把这个环扩展,记录l,r指针,扫描,随便搞一下就能求得答案。
所以本蒟蒻想到的具体做法就是:先topsort一下,把环给找出来,边topsort边DP,然后遇到环再dfs就OK了
不说废话看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+;
int n,cnt,tim,hd[N],v[N],nxt[N],w[N],c[N],du[N],vis[N],q[N];
ll ans,d[N],f[N],a[N],b[N];
void add(int x,int y,int z){v[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt,w[cnt]=z;}
void dfs(int u,int k)
{
c[u]=k;
for(int i=hd[u];i;i=nxt[i])if(!c[v[i]])dfs(v[i],k);
}
void topsort()
{
int qs=,qe=;
for(int i=;i<=n;i++)if(du[i]==)q[qe++]=i;
while(qs<qe)
{
int u=q[qs++];
for(int i=hd[u];i;i=nxt[i])
if(du[v[i]]>)
{
du[v[i]]--;
d[c[u]]=max(d[c[u]],f[u]+f[v[i]]+w[i]);
f[v[i]]=max(f[v[i]],f[u]+w[i]);
if(du[v[i]]==)q[qe++]=v[i];
}
}
}
void dp(int x,int tp)
{
int m=,y=x,i;
do{
a[++m]=f[y];
du[y]=;
for(i=hd[y];i;i=nxt[i])
if(du[v[i]]>){b[m+]=b[m]+w[i];y=v[i];break;}
}while(i);
if(m==)
{
int len=;
for(int i=hd[y];i;i=nxt[i])if(v[i]==x)len=max(len,w[i]);
d[tp]=max(d[tp],f[x]+f[y]+len);
return;
}
for(int i=hd[y];i;i=nxt[i])if(v[i]==x){b[m+]=b[m]+w[i];break;}
for(int i=;i<=m;i++)a[m+i]=a[i],b[m+i]=b[m+]+b[i];
int l=,r=;
l=r=q[]=;
for(int i=;i<*m;i++)
{
while(l<=r&&i-q[l]>=m)l++;
d[tp]=max(d[tp],b[i]-b[q[l]]+a[i]+a[q[l]]);
while(l<=r&&a[q[r]]+b[i]-b[q[r]]<=a[i])r--;
q[++r]=i;
}
}
int main()
{
scanf("%d",&n);
for(int i=,x,y;i<=n;i++)scanf("%d%d",&x,&y),add(i,x,y),add(x,i,y),du[x]++,du[i]++;
for(int i=;i<=n;i++)if(!c[i])dfs(i,++tim);
topsort();
for(int i=;i<=n;i++)
if(du[i]>&&!vis[c[i]])vis[c[i]]=,dp(i,c[i]),ans+=d[c[i]];
printf("%lld",ans);
}
bzoj1791[IOI2008]Island岛屿(基环树+DP)的更多相关文章
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- BZOJ 1791: [IOI2008]Island 岛屿 - 基环树
传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...
- 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 ...
- P4381 [IOI2008]Island(基环树+单调队列优化dp)
P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...
随机推荐
- python爬虫之git的使用(windows下pycharm使用)
相信很多同学学会了git或者github以后都不知道怎么跟windows上的pycharm连在一起工作,那么下面我们开始介绍简单的安装和使用方法. 一.安装 1.首先你的有一个github的账户.注册 ...
- ubuntu18.04 安装 php7.2
sudo apt-get install software-properties-common python-software-properties sudo add-apt-repository p ...
- Linux基础学习(11)--Shell编程
第十一章——Shell编程 一.基础正则表达式 1.正则表达式与通配符(*,?,[ ]): 2.基础正则表达式: 二.字符截取命令 1.cut字段提取命令: 空格分割时,不知道空格有多少个,无法分割行 ...
- python RSA 加密与签名
PyCrypto装起来就简单多了,我是直接 sudo easy_install pycrypto 直接搞定的 先生成rsa的公私钥:打开控制台,输入 openssl 再输入 genrsa -out p ...
- SpringBoot之修改单个文件后立刻生效
问题: 在使用SpringBoot进行开发时,如果修改了某个文件比如前端页面html,不能立刻起效. 解决: 在idea中打开修改后的文件,使用快捷键Ctrl+Shift+F9 进行重新编译,然后刷新 ...
- git reset 版本回退的三种用法总结
git reset (–mixed) HEAD~1 回退一个版本,且会将暂存区的内容和本地已提交的内容全部恢复到未暂存的状态,不影响原来本地文件(未提交的也不受影响) git reset –soft ...
- DotNetty 实现 Modbus TCP 系列 (一) 报文类
本文已收录至:开源 DotNetty 实现的 Modbus TCP/IP 协议 Modbus TCP/IP 报文 报文最大长度为 260 byte (ADU = 7 byte MBAP Header ...
- 转载:关于JESD204B转换器与FPGA匹配的设计关键点
http://www.dzsc.com/data/2014-11-27/107442.html 随着更多的模数转换器(ADC)和数模转换器(DAC)支持最新的JESD204B串行接口标准,出现了FPG ...
- java 中的包概念
Java 中的包package, 就是电脑中的文件夹.我们平时在工作中,文件太多时,都会新建文件夹进行分类管理,java 中的包也是类似的道理,当我们的类太多时,也需要进行分类管理,这时我们就会把类文 ...
- hdu-1238(kmp+枚举)
题意:给你n个字符串,问你这里面最长的公共子串的长度是多少,一个公共子串的反串也算,比如样例二: 解题思路:随便找一个字符,枚举它的子串然后跑kmp就行了,很多人的博客都是用string类里面的函数来 ...