题目实际上是求环套树森林中每个环套树的直径。

对于环套树的直径,可以先找到这个环套树上面的环。然后把环上的每一点都到达的外向树上的最远距离作为这个点的权值。

那么直径一定就是从环上的某个点开始,某个点结束的。

把环拆成链,定义dp[i]表示第i个点为结束点的最远距离,显然有dp[i]=val[j]+sum[i]-sum[j-1]+val[i].显然可以用单调队列优化这个DP。

剩下的就是这样依次统计每个环套树的直径之和。

对于环套树上找环可以借鉴最小树形图找环的技巧。

首先将边定向,保证每个点的出度为1.由于环套树的性质,这样从这颗树的任意点开始搜索,一定会回到原来访问过的点,在这个过程中记录好每个点的前驱。

就可以很easy的将这个环找出来。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <cctype>
#include <iostream>
#define N 1050000
using namespace std;
inline int getc() {
static const int L = <<;
static char buf[L],*S=buf,*T=buf;
if(S==T){
T=(S=buf)+fread(buf,,L,stdin);
if(S==T)return EOF;
}
return *S++;
}
inline int getint() {
int c;
while(!isdigit(c = getc()));
int tmp = c-'';
while(isdigit(c=getc()))
tmp=(tmp<<)+(tmp<<)+c-'';
return tmp;
}
struct Syndra
{
int u,v,len,next;
}e[N];
struct Fiona
{
int edge,flag1,flag2;
long long temp,max1,max2;
}s[N];
int head[N],cnt,n;
int visit[N],next[N],len[N];
int i,j,k;
long long sa[N],pre[N],ans;
void add(int u,int v,int len)
{
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].len=len;
e[cnt].next=head[u];
head[u]=cnt;
}
int que[N<<];
long long sum[N<<],ret;
long long dp(int num)
{
int top,tail;
int u,b,star;
int et;
for(et=;et<(num<<);et++)
{
sum[et]=sum[et-]+pre[(et-)>=num?(et--num):(et-)];
}
top=tail=;
/*
que[top]=0;
for(et=1;et<(num<<1);et++)
{
while(et-que[top]>=num)top++;
u=que[top];
ret=max(ret,sa[et>=num?et-num:et]+sa[u>=num?u-num:u]+sum[et]-sum[u]);
b=que[tail];
que[++tail]=et;
for(star=tail;star>top;b=que[star-1])
{
if(sum[et]-sum[b]+sa[b]<sa[et])
{
que[star]=b;
que[--star]=et;
}
else break;
}
tail=star;
}
*/
que[tail++]=;
for(et=;et<(num<<);++et)
{
while(top<tail&&et-que[top]>=num)++top;
u=que[top];
ret=max(ret,sa[et>=num?et-num:et]+sa[u>=num?u-num:u]+sum[et]-sum[u]);
while(top<tail&&sa[et>=num?et-num:et]>=sa[que[tail-]>=num?que[tail-]-num:que[tail-]]+sum[et]-sum[que[tail-]])--tail;
que[tail++]=et;
}
return ret;
}
void build()
{
cnt=;
memset(head,,sizeof(head));
memset(visit,,sizeof(visit));
n=getint();
for(i=;i<=n;i++)
{
next[i]=getint();
len[i]=getint();
add(next[i],i,len[i]);
}
}
stack<int>sk;
int fa[N];
void dfs(int x)
{
if(s[x].edge==)
{
sk.pop();
if(s[x].flag2)ret=max(ret,s[x].max1+s[x].max2);
if(visit[x]==-)
return ;
x = sk.top();
{
int v,tt=s[x].edge;
v=e[tt].v;
visit[v]=i;
s[x].temp=s[v].max1+e[tt].len;
if(s[x].max1<s[x].temp)
{
if(s[x].flag1)s[x].max2=s[x].max1,s[x].flag2=;
else s[x].flag1=;
s[x].max1=s[x].temp;
}
else if(s[x].max2<s[x].temp)s[x].max2=s[x].temp,s[x].flag2=;
s[x].edge=e[tt].next;
}
return ;
}
int v,tt=s[x].edge;
v=e[tt].v;
if(visit[v]==-)
{
s[x].edge=e[tt].next;
return ;
}
fa[v]=x;
s[v].edge=head[v];
sk.push(v);
}
long long handle(int x)
{
s[x].edge=head[x];
sk.push(x);
while(!sk.empty())
{
dfs(sk.top());
}
return s[x].max1;
}/*handle(long long)+dfs(void)=dfs(long long)*/
/*long long dfs(int x)
{
int et,v,flag1,flag2;
long long max1,max2;
for(max1=max2=0,flag1=flag2=0,et=head[x];et;et=e[et].next)
{
v=e[et].v;
if(visit[v]==-1)continue;
temp=dfs(v)+e[et].len;
visit[v]=i;
if(max1<temp)
{
if(flag1)max2=max1,flag2=1;
max1=temp;
flag1=1;
}
else if(max2<temp)max2=temp,flag2=1;
}
if(flag2)ret=max(ret,max1+max2);
return max1;
}*/
int main()
{
int u,v;
build();
for(i=;i<=n;i++)
{
if(!visit[i])
{
for(u=i;!visit[u];u=next[u])
{
visit[u]=i;
}
if(visit[u]==i)
{
ret=;cnt=;
visit[u]=-;
for(v=next[u];v!=u;v=next[v])
{
visit[v]=-;
}
v=u;
do{
pre[cnt]=len[v];
sa[cnt++]=handle(v);
v=next[v];
}while(v!=u);
ans+=dp(cnt);
}
}
}
cout<<ans;
return ;
}

BZOJ 1791 岛屿(环套树+单调队列DP)的更多相关文章

  1. BZOJ3242 [Noi2013]快餐店 【环套树 + 单调队列dp】

    题目链接 BZOJ3242 题解 题意很清楚,找一点使得最远点最近 如果是一棵树,就是直径中点 现在套上了一个环,我们把环单独拿出来 先求出环上每个点外向树直径更新答案,并同时求出环上每个点外向的最远 ...

  2. BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]

    基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...

  3. bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】

    我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...

  4. 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] D ...

  5. 1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP

    1304F2 - Animal Observation (hard version) 线段树or单调队列 +DP 题意 用摄像机观察动物,有两个摄像机,一个可以放在奇数天,一个可以放在偶数天.摄像机在 ...

  6. BZOJ 1012 线段树||单调队列

    非常裸的线段树  || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...

  7. CF480E Parking Lot(单调队列+dp然鹅并不是优化)

    (全英文题面所以直接放化简题意) 题意:在一个二维平面内,初始有一些点,然后每个时间点加入一些点,对每个时间点求平面内最大的无障碍正方形 (这次的题目是真的神仙啊...) 首先,考虑暴力,如果对每一个 ...

  8. POJ 3017 单调队列dp

    Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 ...

  9. [TyvjP1313] [NOIP2010初赛]烽火传递(单调队列 + DP)

    传送门 就是个单调队列+DP嘛. ——代码 #include <cstdio> ; , t = , ans = ~( << ); int q[MAXN], a[MAXN], f ...

随机推荐

  1. MapWindow记录

    增加MapWinGIS的新功能,编译完MapWinGIS,可以生成Debug和Release版本的x64和Win32四种版本, 自己基于c#的Mapwindow如果要用到新添加的功能,此时就得重新注册 ...

  2. 厦门Uber优步司机奖励政策(12月28日到1月3日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. NB-IOT使用LWM2M移动onenet对接之MTU最大传输单元设置

    1. 最近遇到的一个项目NB-IOT使用LWM2M移动onenet对接,要求设置传输的MTU,因此首先需要搞懂MTU是什么? 以太网的MTU值是1500 bytes,假设发送者的协议高层向IP层发送了 ...

  4. 全局脚手架了解一下【fle-cli】

    本文来自网易云社区 介绍 fle-cli旨在帮助我们从复杂繁琐的编译配置中解放出来,全身心地投入业务开发中,提高开发效率. 它是真正意义上的全局脚手架,区别于市面上其他的全局脚手架,它不会在项目工程中 ...

  5. hadoop 家族图

    hadoop家族

  6. WPF DataGridRow Event

    CM(Caliburn.Micro)框架绑定DataGridRow事件 <DataGrid.ItemContainerStyle> <Style TargetType="D ...

  7. python 定位文件目录

    经常有引用文件的地方,所以整理了一下如何定位文件目录的方法 定位当前文件的目录 import os file_path = os.path.dirname(__file__) 定位当前文件的父目录 i ...

  8. 165. Merge Two Sorted Lists【LintCode by java】

    Description Merge two sorted (ascending) linked lists and return it as a new sorted list. The new so ...

  9. hdu刷题2

    hdu1021 给n,看费波纳列数能否被3整除 算是找规律吧,以后碰到这种题就打打表找找规律吧 #include <stdio.h> int main(void) { int n; whi ...

  10. block inline 和 inline-block

    概念 block和inline这两个概念是简略的说法,完整确切的说应该是 block-level elements (块级元素) 和 inline elements (内联元素). block元素通常 ...