一道基环树的直径

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. TensorFlow 语法

    dataset = tf.data.TextLineDataset(file_path) 生成一个dataset,dataset中的每一个元素就对应了文件中的一行

  2. js判断是否为undefined

    typeof(isadmin)=="undefined"需要使用typeof才能判断

  3. Oracle VM VirtulBox 安装Ubuntu16.04

    曾经自己在电脑中检索到Ubuntu kylin 16-10.vmdk 后就通过. 这种方式就进行了新建. 后自己从http://www.gaofumei.net/linux-download/783. ...

  4. yyyy-MM-dd 转换为年月日

      yyyy-MM-dd 转换为年月日   先用parse转成date型,再用format转成string. Date date = new SimpleDateFormat("yyyy-M ...

  5. 响应式的账号登录界面模板完整代码,内置form表单和js控件

    响应式的账号登录界面模板,内置form表单和js控件 <!DOCTYPE html> <html lang="en"><head><met ...

  6. 径向模糊(Radial Blur)

    [径向模糊(Radial Blur)] 径向模糊,是一种从中心向外呈幅射状的逐渐模糊的效果,在图形处理软件photoshop里面也有这个模糊滤镜.而在游戏中常常用来模拟一些动感的效果,如鬼泣4中的场景 ...

  7. Activity 与 Task

    [Activity 与 Task] A task is a collection of activities that users interact with when performing a ce ...

  8. 读取excel表格以及生成自动化报告

    数据库读取 标签(空格分隔): 数据库读取 读excel数据xlrd 当登录的账号有多个的时候,我们一般用excel存放测试数据,本节课介绍,python读取excel方法,并保存为字典格式. 1.先 ...

  9. 执行SDK的aapt报错./aapt: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./aapt)

    问题| 执行SDK下的aapt报错./aapt: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./aapt)   ../ ...

  10. jpa orderby

    return criteriaQuery.where(in).orderBy(new OrderImpl(root.get("field1"))).getRestriction() ...