一道基环树的直径

BZOJ原题链接

洛谷原题链接

又是一道实现贼麻烦的题。。

显然公园其实是基环树森林,求的最长距离其实就是求每一棵基环树的直径的总和。

对于每棵基环树,其直径要么经过环,要么是某个环上点的子树的直径。所以我们可以先找出它的环,然后对环上的每个点进行\(dfs\)(不能经过环上的点),找出该点的子树的直径和数组\(D\),表示该点到子树中的叶子节点的最大距离。

然后考虑经过环的距离,设当前枚举到两个点\(x,y\),则长度为\(D[x]+D[y]+dis(x,y)\),这个可以通过单调队列来优化,维护一个最大值即可。

#include<cstdio>
using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
int fi[N], di[N << 1], da[N << 1], ne[N << 1], cr[N], cr_d[N], q[N << 1], po[N << 1], l, cb, fp, n;
ll D[N], dis[N << 1], fr;
bool v[N], egv[N << 1], vis[N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c<'0' || c>'9'; c = getchar())
p |= c == '-';
for (; c >= '0'&&c <= '9'; c = getchar())
x = x * 10 + (c - '0');
return p ? -x : x;
}
inline void add(int x, int y, int z)
{
di[++l] = y;
da[l] = z;
ne[l] = fi[x];
fi[x] = l;
}
inline ll maxn(ll x, ll y)
{
return x > y ? x : y;
}
void dfs(int x)
{
int i, y;
v[x] = 1;
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (!egv[i])
{
cr[y] = x;
cr_d[y] = da[i];
egv[i] = egv[i & 1 ? i + 1 : i - 1] = 1;
if (v[y])
cb = y;
dfs(y);
}
}
}
void dfs_2(int x, ll d, int fa)
{
int i, y;
if (fr < d)
{
fr = d;
fp = x;
}
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (!vis[y] && y != fa)
{
dfs_2(y, d + da[i], x);
D[x] = maxn(D[x], D[y] + da[i]);
}
}
}
void dfs_3(int x, ll d, int fa)
{
int i, y;
fr = maxn(fr, d);
for (i = fi[x]; i; i = ne[i])
{
y = di[i];
if (!vis[y] && y != fa)
dfs_3(y, d + da[i], x);
}
}
int main()
{
int i, j, x, y, k, head, tail;
ll s = 0, ma;
n = re();
for (i = 1; i <= n; i++)
{
x = re();
y = re();
add(i, x, y);
add(x, i, y);
}
for (i = 1; i <= n; i++)
if (!v[i])
{
ma = 0;
dfs(i);
j = cb;
k = 0;
do
{
vis[j] = 1;
k++;
dis[k + 1] = dis[k] + cr_d[j];
po[k] = j;
j = cr[j];
} while (j^cb);
do
{
vis[j] = 0;
fr = 0;
dfs_2(j, 0, 0);
fr = 0;
dfs_3(fp, 0, 0);
vis[j] = 1;
ma = maxn(ma, fr);
k++;
dis[k + 1] = dis[k] + cr_d[j];
po[k] = j;
j = cr[j];
} while (j^cb);
head = 1;
tail = 0;
for (j = 1; j <= k; j++)
{
while (j - q[head] >= (k >> 1))
head++;
if (head <= tail)
ma = maxn(ma, D[po[j]] + D[po[q[head]]] + dis[j] - dis[q[head]]);
else
ma = maxn(ma, D[po[j]]);
while (head < tail&&D[po[j]] - dis[j] >= D[po[q[tail]]] - dis[q[tail]])
tail--;
q[++tail] = j;
}
s += ma;
}
printf("%lld", s);
return 0;
}

BZOJ1791或洛谷4381 [IOI2008]Island的更多相关文章

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

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

  2. BZOJ1791: [Ioi2008]Island 岛屿

    BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...

  3. [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)

    [bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...

  4. bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp

    1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1826  Solved: 405[Submit][S ...

  5. bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿

    http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...

  6. 【洛谷3224/BZOJ2733】[HNOI2012]永无乡 (Splay启发式合并)

    题目: 洛谷3224 分析: 这题一看\(n\leq100000\)的范围就知道可以暴力地用\(O(nlogn)\)数据结构乱搞啊-- 每个联通块建一棵Splay树,查询就是Splay查询第k大的模板 ...

  7. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  8. 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.

    没有上司的舞会  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...

  9. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

随机推荐

  1. mab算法

    https://zhuanlan.zhihu.com/p/21388070?refer=resyschina 专治选择困难症——bandit算法 改善:https://zhuanlan.zhihu.c ...

  2. /src/applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  3. 手机端head部分

    <!doctype html> <html lang="zh"> <head> <meta charset="utf-8&quo ...

  4. KMP与AC自动机模板

    HDU 1711 Number Sequence(KMP模板题) http://acm.hdu.edu.cn/showproblem.php?pid=1711 #include<bits/std ...

  5. Fixation index

    :或者1.简单介绍 固定指数(FST)是一种由遗传结构决定的种群分化指标.它通常是由遗传多态性数据,如单核苷酸多态性(SNP)或微卫星估计.作为莱特f统计的一个特例,它是种群遗传学中最常用的统计方法之 ...

  6. day15模块内容

    1.生成器表达式 先说三元表达式如下 res = [i for i in range(10) if 1 > 5] 这样res就是一个列表6,7,8,9] 只要在这个基础上稍加调整,如下 方括号改 ...

  7. dedecms list 添加自定义字段方法

    在内容模型管理中,添加字段时需这样:

  8. pta7-18奥运排行榜(模拟)

    题目链接:https://pintia.cn/problem-sets/1101307589335527424/problems/1101314114867245056 题意:给n个国家,以及每个国家 ...

  9. 【转】关于easyui的窗口和tab页面不执行js说明

    原地址:http://www.jeasyuicn.com/post-49.html 一直以来群里里面很多人反应,在用tab加载界面的时候,界面里面的js不会执行.今天GodSon在此说明一下原因. 不 ...

  10. 【python-sql】sql操作时遇到的坑

    针对python的sql语句的封装以及调用: python的db操作类: # -*- coding: utf-8 -*- # coding=utf-8 import MySQLdb class Dat ...