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 找环是可以拓扑的,但是利用性质有更 ...
随机推荐
- localStorage基本了解及使用
以下内容来自: https://www.cnblogs.com/st-leslie/p/5617130.html 感谢大佬的分享 一.什么是localStorage.sessionStorage 在 ...
- Python-数据库连表查询、子查询
连表查询 [实例]通过例子来熟悉连表查询的概念 # 第一步:建表 # 建立英雄职业分类表格 create table classification( id int, name varchar(20) ...
- caoz的梦呓:信息安全,别为了芝麻丢了西瓜
猫宁!!! 参考链接:https://mp.weixin.qq.com/s/z6UI-tdhN1CGdqQQuglLVQ 对方公众号:caoz的梦呓 我之前写微博的时候,经常就有读者反馈说,你怎么用3 ...
- DARTS代码分析(Pytorch)
最近在看DARTS的代码,有一个operations.py的文件,里面是对各类点与点之间操作的方法. OPS = { 'none': lambda C, stride, affine: Zero(st ...
- netcore程序部署 ubuntu 16.0.4 报错 The type initializer for 'System.Net.Http.CurlHandler'的解决方案
最近业务扩展需要把netcore程序部署到ubuntu 16.0.4上,因为代码里面用到了HttpClient 请求. 部署ubuntu后一直报错 参考地址:https://github.com/do ...
- 【DSP开发】C6678的中断控制器
分两层,一层是每个core内部的中断控制器,这个叫interrupt controller,简写intc:一层是整个芯片的,属于芯片级的,在每个core的外面,这个叫chip-level interr ...
- 【Python】【demo实验2】【打印乘法口诀表】
打印乘法口诀表 源代码: # encoding=utf-8 for i in range(1,10): print("\n") for j in range(1,10): if i ...
- 什么是分布式关系型数据库服务 DRDS
DRDS 产品简介 DRDS 是一款基于 MySQL 存储.采用分库分表技术进行水平扩展的分布式 OLTP 数据库服务产品,支持 RDS for MySQL 以及 POLARDB for MySQL, ...
- 单页面应用 之 项目中集成插件vue-router
\es6\my-complex-project>npm install vue-router -S (S 表示这个包下载到,当前的项目中) 导入写好的 router 这里尽量使用 @ ...
- PreparedStatement 以及事务的注意事项
a).PreparedStatement 可以进行批量操作,但是与Statement有一定的区别 1. Statement可以进行不同sql语句的批量操作 即可以同时进行 crud 操作. Strin ...