bzoj 1791: [Ioi2008]Island 岛屿
#include<iostream>
#include<cstdio>
#define M 1000009
using namespace std;
int q[*M],cnt,n,head[M],next[*M],u[*M],l[*M],du[M],c[M],t,v[M];
long long f[M],d[M],d1[*M],a[*M],ans;
void jia(int a1,int a2,int a3)
{
cnt++;
next[cnt]=head[a1];
head[a1]=cnt;
u[cnt]=a2;
l[cnt]=a3;
du[a1]++;
return;
}
void dfs(int k,int x)
{
c[x]=k;
for(int i=head[x];i;i=next[i])
if(!c[u[i]])
dfs(k,u[i]);
return;
}
void tuopu()
{
int h=,t=;
for(int i=;i<=n;i++)
if(du[i]==)
{
t++;
q[t]=i;
}
for(;h<t;)
{
h++;
int p=q[h];
for(int i=head[p];i;i=next[i])
if(du[u[i]]!=)
{
du[u[i]]--;
d[c[p]]=max(d[c[p]],f[p]+f[u[i]]+l[i]);
f[u[i]]=max(f[u[i]],f[p]+l[i]);
if(du[u[i]]==)
{
t++;
q[t]=u[i];
}
}
}
}
void dp(int t1,int x)
{
int m=,y=x,i;
do
{
a[++m]=f[y];
du[y]=;
for(i=head[y];i;i=next[i])
if(du[u[i]]>)
{
d1[m+]=d1[m]+l[i];
y=u[i];
break;
}
}while(i);
if(m==)
{
int qq=;
for(int i=head[y];i;i=next[i])
if(u[i]==x)
qq=max(qq,l[i]);
d[c[x]]=max(d[c[x]],a[]+a[]+qq);
return;
}
for(int i=head[y];i;i=next[i])
if(u[i]==x)
{
d1[m+]=d1[m]+l[i];
break;
}
for(int i=;i<=m;i++)
{
a[m+i]=a[i];
d1[m+i]=d1[m+]+d1[i];
}
int h=t=;
q[]=;
for(int i=;i<=*m;i++)
{
for(;h<=t&&i-q[h]>=m;h++);
d[t1]=max(d[t1],a[q[h]]+a[i]+d1[i]-d1[q[h]]);
for(;h<=t&&a[q[t]]-d1[q[t]]<=a[i]-d1[i];t--);
t++;
q[t]=i;
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int a1,a2;
scanf("%d%d",&a1,&a2);
jia(i,a1,a2);
jia(a1,i,a2);
}
for(int i=;i<=n;i++)
if(!c[i])
{
t++;
dfs(t,i);
}
tuopu();
for(int i=;i<=n;i++)
if(du[i]>&&!v[c[i]])
{
v[c[i]]=;
dp(c[i],i);
ans+=d[c[i]];
}
printf("%lld\n",ans);
return ;
}
这个题建出图来之后,是一个基环树森林,先把非环部分的最长链用DP求出来,在把环拆开,变为两倍,找环上两点之间的距离加上在这两个点的子树中,以这两个点为端点的最长链的
长度,注意如果是两个点的环,需要特判,因为不一定能找到那条最长的边。
bzoj 1791: [Ioi2008]Island 岛屿的更多相关文章
- BZOJ 1791: [IOI2008]Island 岛屿 - 基环树
传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...
- bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】
我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...
- bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿
http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...
- bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1826 Solved: 405[Submit][S ...
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- BZOJ1791: [Ioi2008]Island 岛屿
BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...
- 【BZOJ 1791】 [Ioi2008]Island 岛屿
Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- iOS 设置button中图文位置
方法一. -(CGRect)imageRectForContentRect:(CGRect)contentRect { return CGRectMake(self.width - kImage ...
- poj2194Stacking Cylinders
链接 可以根据反余弦和反正切算出角a和b的值, 然后向量旋转就可以了,图中的状态旋转rotate((2,0),a+b) 反状态把角度反过来,点取(-2,0)即可. 不知道是不是理解错了,题意写着两圆 ...
- JS自总结
1.js获得当前元素 event.srcElement: 获取当前父元素 event.srcElement.parentElement var rowIndex = e.parentE ...
- Docker-创建支持ssh服务的镜像
这里测试tomcat镜像安装ssh服务 1.启动镜像 [root@wls12c docker]$ docker run -d tomcat:centos 844bdde121a03174f3abd22 ...
- Android dex分包方案
当一个app的功能越来越复杂,代码量越来越多,也许有一天便会突然遇到下列现象: 1. 生成的apk在2.3以前的机器无法安装,提示INSTALL_FAILED_DEXOPT 2. 方法数量过多,编译时 ...
- 使用==比较String类型
String类型的比较 public class StringDemo { public static void main(String[] args) { String s1 = "abc ...
- static final的理解
static: static静态,可以修饰类,成员变量,成员方法,代码块.static修饰的成员变量和方法独立于该类的任何对象,也就是被类的所有成员共享,这要这个类被加载,虚拟机就能根据类名在运行时数 ...
- Machine Learning for hackers读书笔记(三)分类:垃圾邮件过滤
#定义函数,打开每一个文件,找到空行,将空行后的文本返回为一个字符串向量,该向量只有一个元素,就是空行之后的所有文本拼接之后的字符串 #很多邮件都包含了非ASCII字符,因此设为latin1就可以读取 ...
- centos svn服务器安装
1.安装必须的软件 yum install httpd httpd-devel subversion mod_dav_svn mod_auth_mysql 2.创建代码库 mkdir -p /root ...
- Qt之QParallelAnimationGroup
简述 QParallelAnimationGroup类提供动画的并行组. QParallelAnimationGroup - 一个动画容器,当它启动的时候它里面的所有动画也启动,即:并行运行所有动画, ...