非递归版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 基环树直径的更多相关文章

  1. luogu 4381 [IOI2008]Island 单调队列 + 基环树直径 + tarjan

    Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...

  2. 『Island 基环树直径』

    Island(IOI 2008) Description 你准备浏览一个公园,该公园由 N 个岛屿组成,当地管理部门从每个岛屿 i 出发向另外一个岛屿建了一座长度为 L_i 的桥,不过桥是可以双向行走 ...

  3. [IOI2008/BZOJ1791 岛屿](处理基环树的小技巧&基于bfs树形DP)

    IOI2008/BZOJ1791 岛屿 题目大意是在一个基环树森林里求每一棵基环树的直径①的和. 其实就是树的直径的基环树升级版.我们先把环找出来,然后从环上的每一个节点x出发,并且不经过环上其他节点 ...

  4. 【BZOJ1791】【IOI2008】【基环树】island(status第一速度)

      1791: [Ioi2008]Island 岛屿  Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 908  Solved: 159 [Su ...

  5. bzoj1791[IOI2008]Island岛屿(基环树+DP)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...

  6. D4 树的直径、重心以及基环树

    第一题第二题鉴上我前几篇博客poj1985 poj1849:https://www.cnblogs.com/Tyouchie/p/10384379.html 第三题:数的重心:poj1655 来自sj ...

  7. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

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

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

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

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

随机推荐

  1. 让mysql返回的结果按照传入的id的顺序排序

    比如id为 1,3,5,44,66,32,21,6 那么返回的结果顺序也是这个顺序   $sql = "select * from ".$this->tableName(). ...

  2. minio 集群启动方法

    Sample: export MINIO_ACCESS_KEY=<TENANT1_ACCESS_KEY> export MINIO_SECRET_KEY=<TENANT1_SECRE ...

  3. 车载导航应用中基于Sketch UI主题实现

    1.导读 关于应用的主题定制,相信大家或多或少都有接触,基本上,实现思路可以分为两类: 内置主题(应用内自定义style) 外部加载方式(资源apk形式.压缩资源.插件等) 其实,针对不同的主题定制实 ...

  4. C++学习笔记-const

    const在C++中有着大量的运用,深刻理解const有助于进一步理解C++. const基础知识 int main() { const int a;//C++中必须初始化 int const b;/ ...

  5. 一篇文章搞懂python2、3编码

    说在前边: 编码问题一直困扰着每一个程序员的编程之路,如果不将它彻底搞清楚,那么你的的这条路一定会走的格外艰辛,尤其是针对使用python的程序员来说,这一问题更加显著, 因为python有两个版本, ...

  6. CDH的mysql主从准备

    参考: https://www.cnblogs.com/yinzhengjie/p/10371899.html https://www.sysit.cn/blog/post/sysit/CDH6.2. ...

  7. DOS sqlcmd

    C:\>sqlcmd -? Microsoft (R) SQL Server 命令行工具版本 12.0.2000.8 NT版权所有 (c) 2014 Microsoft.保留所有权利. 用法: ...

  8. (一)使用twisted Deferred

    一.开篇 为什么是twisted,twisted作为一个python网络编程框架,出道早,但一直不温不火,这几年和tornado比起来,更是近乎销声匿迹:但作为初学者,觉得twisted还是有很多优点 ...

  9. C++学习 之 继承方式(笔记)

    1.继承方式的分类 继承方式有公有继承,私有继承,保护继承.不同之处在于指定派生类的基类时使用的关键字不同:公有继承使用关键字public,私有继承使用关键字private,保护继承使用关键字prot ...

  10. Django发送邮件和itsdangerous模块的配合使用

    项目需求:用户注册页面注册之后,系统会发送一封邮件到用户邮箱,用户点击链接以激活账户,其中链接中的用户信息需要加密处理一下 其中激活自己邮箱的smtp服务的操作就不在加以说明,菜鸟教程上有非常清晰的讲 ...