一道基环树的直径

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. How to fix the bug “Expected "required", "optional", or "repeated".”?

    参考:https://github.com/tensorflow/models/issues/1834 You need to download protoc version 3.3 (already ...

  2. JS----获取DOM元素的方法(8种)

    什么是HTML DOM 文档对象模型(Document Object Model),是W3C组织推荐的处理可扩展置标语言的标准编程接口.简单理解就是HTML DOM 是关于如何获取.修改.添加或删除 ...

  3. JDK8中JVM堆内存划分

    一:JVM中内存 JVM中内存通常划分为两个部分,分别为堆内存与栈内存,栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址. JVM全部的对象信息都 存放在堆内存中.相比 ...

  4. shell脚本-删除当天日期前3个月的数据表

    #!/bin/bash #author:skycheng #get current date string datestr=`date +'%Y-%m-%d'` start_time=`date +' ...

  5. Java读取.properties配置文件并连接数据库

    1.读取配置文件 //Properties集合 流对象读取键值对 public static void getNum() throws Exception { Properties p=new Pro ...

  6. Velocity Obstacle

    [Velocity Obstacle] Two circular objects A,B, at time t(0), with velocity V(A),V(B). A represent the ...

  7. JavaScript Drag处理

    [JavaScript Drag处理] 在拖动目标上触发事件 (源元素): ondragstart - 用户开始拖动元素时触发 ondrag - 元素正在拖动时触发 ondragend - 用户完成元 ...

  8. 七 shelve模块

    shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型 import shelve f=shelve.o ...

  9. Lua的闭包详解(终于搞懂了)

    词法定界:当一个函数内嵌套另一个函数的时候,内函数可以访问外部函数的局部变量,这种特征叫做词法定界 table.sort(names,functin (n1,n2) return grades[n1] ...

  10. 问题1:canvas绘制图片加载不出来

    <head> <script src="js/index.js" type="text/javascript" charset="u ...