BZOJ1791 基环树直径
非递归版4S
/**************************************************************
Problem: 1791
User: 18357
Language: C++
Result: Accepted
Time:4556 ms
Memory:120132 kb
****************************************************************/
#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[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;
}
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 ;
}
//BZOJ1791
自己写的递归RE待修改版
/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int MAXN = 1e6 + , MAXM = 1e6 + ;
int to[MAXM << ], nxt[MAXM << ], Head[MAXN], ed = ;
int value[MAXM << ];
int i, v;
inline void addedge(int u, int v, int val)
{
to[++ed] = v;
nxt[ed] = Head[u];
value[ed] = val;
Head[u] = ed;
}
inline void read(int &v)
{
v = ;
char c = ;
int p = ;
while (c < '' || c > '')
{
if (c == '-')
{
p = -;
}
c = getchar();
}
while (c >= '' && c <= '')
{
v = (v << ) + (v << ) + c - '';
c = getchar();
}
v *= p;
}
bool circle[MAXN];
int vis[MAXN], cnt;
int nnxt[MAXN], nxtcircle[MAXN];
int que[MAXN << ];
ll dpd[MAXN], sum[MAXN << ], pre[MAXN];
ll sa[MAXN], ansnow, anser;
stack<int> sk;
void dfs(int x, int pre)
{
vis[x] = ;
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (pre != - && i == (pre ^ ))
{
continue;
}
if (vis[v] == )
{
circle[x] = true;
nxtcircle[x] = nnxt[x] = i;
int cur;
cur = to[nxtcircle[x]];
while (cur != x)
{
circle[cur] = true;
nxtcircle[cur] = nnxt[cur];
cur = to[nxtcircle[cur]];
}
}
else if (vis[v] == )
{
continue;
}
else
{
nnxt[x] = i;
dfs(v, i);
}
}
vis[x] = ;
}
void ZJdp(int x)
{
vis[x] = ;
for (int v, i = Head[x]; i; i = nxt[i])
{
v = to[i];
if (vis[v])
{
continue;
}
ZJdp(v);
if (!circle[v])
{
ansnow = max(ansnow, dpd[x] + dpd[v] + value[i]);
dpd[x] = max(dpd[x], dpd[v] + value[i]);
} }
}
int main()
{
int n;
int u;
read(n);
for (i = ; i <= n; i++)
{
read(u), read(v);
addedge(i, u, v), addedge(u, i, v);
}
for (i = ; i <= n; i++)
{
if (!vis[i])
{
dfs(i, -);
}
}
mem(vis, );
int top, tail, et, cur;
for (i = ; i <= n; i++)
{
if (circle[i])
{
if (!vis[i])
{
ansnow = ;
ZJdp(i);
top = tail = cnt = ;
que[tail++] = ;
cur = to[nxtcircle[i]];
sa[cnt] = dpd[i];
pre[cnt++] = value[nxtcircle[i]];
while (cur != i)
{
sa[cnt] = dpd[cur];
pre[cnt++] = value[nxtcircle[cur]];
cur = to[nxtcircle[cur]];
}
for (et = ; et < (cnt << ); et++)
{
sum[et] = sum[et - ] + pre[(et - ) >= cnt ? (et - - cnt) : (et - )];
}
for (et = ; et < (cnt << ); ++et)
{
while (top < tail && et - que[top] >= cnt)
{
++top;
}
u = que[top];
ansnow = max(ansnow, sa[et >= cnt ? et - cnt : et] + sa[u >= cnt ? u - cnt : u] + sum[et] - sum[u]);
while (top < tail && sa[et >= cnt ? et - cnt : et] >= sa[que[tail - ] >= cnt ? que[tail - ] - cnt : que[tail - ]] + sum[et] - sum[que[tail - ]])
{
--tail;
}
que[tail++] = et;
}
anser += ansnow;
}
}
}
printf("%lld", anser);
return ;
}
BZOJ1791 基环树直径的更多相关文章
- luogu 4381 [IOI2008]Island 单调队列 + 基环树直径 + tarjan
Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...
- 『Island 基环树直径』
Island(IOI 2008) Description 你准备浏览一个公园,该公园由 N 个岛屿组成,当地管理部门从每个岛屿 i 出发向另外一个岛屿建了一座长度为 L_i 的桥,不过桥是可以双向行走 ...
- [IOI2008/BZOJ1791 岛屿](处理基环树的小技巧&基于bfs树形DP)
IOI2008/BZOJ1791 岛屿 题目大意是在一个基环树森林里求每一棵基环树的直径①的和. 其实就是树的直径的基环树升级版.我们先把环找出来,然后从环上的每一个节点x出发,并且不经过环上其他节点 ...
- 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 908 Solved: 159 [Su ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- D4 树的直径、重心以及基环树
第一题第二题鉴上我前几篇博客poj1985 poj1849:https://www.cnblogs.com/Tyouchie/p/10384379.html 第三题:数的重心:poj1655 来自sj ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...
- bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】
我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...
随机推荐
- Java 多线程爬虫及分布式爬虫架构
这是 Java 爬虫系列博文的第五篇,在上一篇 Java 爬虫服务器被屏蔽,不要慌,咱们换一台服务器 中,我们简单的聊反爬虫策略和反反爬虫方法,主要针对的是 IP 被封及其对应办法.前面几篇文章我们把 ...
- 【AMAD】django-rules -- 强大的Django鉴权库,不需要数据库
动机 简介 个人评分 动机 Django默认的权限原子级别是model级.但是一些时候我们像针对model每条数据库记录都进行权限空,也就是对象级权限控制. 简介 django-rules是一个Dja ...
- ORACLE 左连接 右连接 内连接 外连接 全连接 五中表连接方式
1.左连接 :left join 2.右连接:right join 3.内连接:inner join 4.外连接:outer join 5.全连接:full join
- rabbitmq死信队列消息监听
#邮件通知并发送队列消息#!/bin/bash maillog="/var/log/mq.maillog" message_file="/tmp/mq_message&q ...
- RS232与RS485的功能与区别!
转载于:http://blog.csdn.net/kevinhg/article/details/7367144 RS232接口是1970年由美国电子工业协会(EIA)联合贝尔系统.调制解调器厂家及计 ...
- mysql事务、redo日志、undo日志、checkpoint详解
转载: https://zhuanlan.zhihu.com/p/34650908 事务: 说起mysql innodb存储引擎的事务,首先想到就是ACID(不知道的请google),数据库是如何做到 ...
- 2.bash术语定义
2.术语定义POSIX:基于Unix的一系列操作系统可移植性的标准.Bash主要和POSIX标准第1003.1号中的<Shell和使用工具>有关.空白符:一个空格或者制表符.内部命令:在s ...
- sql server update语句
update语句 --Update 语句用于修改表中的数据 语法:update 表名称 set 列名称 = 新值 where 列名称 = 某值 --更新某一行的若干列,set字句中用','隔开
- 第五篇 jQuery特效与动画
5.1 show()与hide()方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...
- Linux小知识:sudo su和su的区别
Linux小知识:sudo su和su的区别 本文是学习笔记,视频地址:https://www.bilibili.com/video/av62836363 su是申请切换root用户,需要申请root ...