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座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
随机推荐
- [转载] Docker网络原则入门:EXPOSE,-p,-P,-link
原文: http://dockone.io/article/455 如果你已经构建了一些多容器的应用程序,那么肯定需要定义一些网络规则来设置容器间的通信.有多种方式可以实现:可以通过--expose参 ...
- Python学习笔记5-元组
元组是用圆括号括起来的,其中的元素之间用逗号隔开 >>> t = 123,'abc',["come","here"] >>> ...
- Android应用程序构成
一个Android应用程序一般是由以下4个组件构成的: 活动(Activity) 意图(Intent) 服务(Service) 内容提供器(Content Provider) 这4个组件是构成andr ...
- uva 11728 Alternate Task
vjudge 上题目链接:uva 11728 其实是个数论水题,直接打表就行: #include<cstdio> #include<algorithm> using names ...
- POJ 3468 线段树裸题
这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了A ...
- zabbix监控系统客户端安装
原文:http://blog.chinaunix.net/uid-25266990-id-3387002.html 测试使用agentd监听获取数据. 服务端的安装可以查看http://blog.ch ...
- 华为 1.static有什么用途?(请至少说明两种)
1.static有什么用途?(请至少说明两种) 1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变. 2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问 ...
- iOS开发 tabBarController选中状态
self.tabBarController.selectedIndex = 0; // 默认是0:
- [C:\Users\Administrator\.IntelliJIdea2016.1\system\tomcat\Unnamed_demo_2\work\Catalina\localhost\demo\org\apache\jsp\index_jsp.java]
http://www.oschina.net/question/1444338_2146454?sort=time
- const修饰指针
关于const修饰指针的情况,一般分为如下4种情况: ; const int *a =&b; //情况1 int const *a =&b; //情况2 int* const a =& ...