【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1023

【题意】

【题解】



如果不考虑有环的情况;

那么有一个经典的求树的直径的方法;

首先;

树的直径的两端的端点必然都在树的叶子上(或在根节点,考虑一条链的情况);



设f[i][0]表示离i这个点最远的叶子节点的距离

f[i][1]表示离i这个点第二远的叶子节点的距离

更新的话

f[x][0]=max(f[son][0]+1);

f[x][1] = max(second(f[son][0])+1);

则可以通过dp求出来所有的节点的f值,取max{f[i][0]+f[i][1]}就是它的直径了;

这里我们可以降成一维的即

ans = max(ans,f[x]+f[son]+1),f[x]=max(f[son]+1);

这里f[x]=max(f[son]+1)在ans更新完后才更新;

这个做法就等同于上面那个做法;

然后该题的情况就是多了一个环;

环的话只要通过环上的非最高点对(x,y);

用f(x)+f(y)+dist(x,y)来更新答案ans;

设环上的最高点为u;

然后用非最高点x的f[x]+dist(x,u)来更新f[x]即可;

挺自然的一个做法吧;

这里的

f(x)+f(y)+dist(x,y)

可以写成

f[x]+f[y]+x-y

这里的x和y是把环破成直线之后x和y在直线上的下标;

x>y

则我们只要维护f[y]-y不下降就可以了

用单调队列搞;

然后因为是最短距离;

所以f[y]-y必须要满足x-y< n/2

这里的n是这个环的长度;

也因为是最短距离;

所以你要把直线的长度延伸到2*n,不然可能会漏解.



【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x) typedef pair<int, int> pii;
typedef pair<LL, LL> pll; const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1 };
const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1 };
const double pi = acos(-1.0);
const int N = 5e4+100; int n, m,k,a[N*2],dfn[N],low[N],num,father[N],f[N],dep[N],ans,q[2*N];
vector <int> g[N]; void input_data()
{
rei(n), rei(m);
rep1(i, 1, m)
{
rei(k);
rep1(j, 1, k)
rei(a[j]);
rep1(j, 1, k - 1)
g[a[j]].push_back(a[j + 1]), g[a[j + 1]].push_back(a[j]);
}
} void dp(int root, int x)
{
int n = dep[x] - dep[root] + 1;
for (int i = x; i != root; i = father[i])
a[n--] = f[i];
a[n] = f[root], n = dep[x] - dep[root] + 1;
rep1(i, n + 1, 2 * n)
a[i] = a[i - n];
int h = 1, t = 1;
q[h] = 1;
rep1(i, 2, n + n / 2)
{
while (h <= t && i - q[h] > n / 2) h++;
ans = max(ans, a[i] + a[q[h]] + i - q[h]);
while (h <= t && a[q[h]] - q[h] <= a[i] - i) t--;
q[++t] = i;
}
rep1(i, 2, n)
f[root] = max(f[root], a[i] + min(i - 1, n - i + 1));
} void Tarjan(int x)
{
dfn[x] = low[x] = ++num;
int len = g[x].size();
rep1(i, 0, len - 1)
{
int y = g[x][i];
if (y == father[x]) continue;
if (dfn[y] == 0) dep[y] = dep[x] + 1, father[y] = x, Tarjan(y);
low[x] = min(low[x], low[y]);
if (dfn[x] < low[y])
ans = max(ans, f[x] + f[y] + 1), f[x] = max(f[x], f[y] + 1);
}
rep1(i, 0, len - 1)
{
int y = g[x][i];
if (y!=father[x] && father[y] != x && dfn[x] < dfn[y])
dp(x, y);
}
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
input_data();
Tarjan(1);
printf("%d\n", ans);
//printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}

【BZOJ 1023】[SHOI2008]cactus仙人掌图的更多相关文章

  1. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...

  2. 【刷题】BZOJ 1023 [SHOI2008]cactus仙人掌图

    Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...

  3. BZOJ 1023: [SHOI2008]cactus仙人掌图 | 在仙人掌上跑DP

    题目: 求仙人掌直径 http://www.lydsy.com/JudgeOnline/problem.php?id=1023 题解: 首先给出仙人掌的定义:满足所有的边至多在一个环上的无向联通图 我 ...

  4. bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列

    %%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 ...

  5. bzoj 1023 [SHOI2008]cactus仙人掌图 ( poj 3567 Cactus Reloaded )——仙人掌直径模板

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 因为lyd在讲课,所以有 ...

  6. bzoj 1023: [SHOI2008]cactus仙人掌图

    这道题是我做的第一道仙人掌DP,小小纪念一下…… 仙人掌DP就是环上的点环状DP,树上的点树上DP.就是说,做一遍DFS,DFS的过程中处理出环,环上的点先不DP,先把这些换上的点的后继点都处理出来, ...

  7. BZOJ.1023.[SHOI2008]cactus仙人掌图(DP)

    题目链接 类似求树的直径,可以用(类似)树形DP求每个点其子树(在仙人掌上就是诱导子图)最长链.次长链,用每个点子节点不同子树的 max{最长链}+max{次长链} 更新答案.(不需要存次长链,求解过 ...

  8. bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】

    本来想先求出点双再一个一个处理结果写了很长发现太麻烦 设f[u]为u点向下的最长链 就是再tarjan的过程中,先照常处理,用最长儿子链和次长儿子链更新按ans,然后处理以这个点为根的环,也就是这个点 ...

  9. 1023: [SHOI2008]cactus仙人掌图 - BZOJ

    Description如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路 ...

  10. 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)

    [题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...

随机推荐

  1. [Angular] Using the Argon 2 Hashing Function In Our Sign Up Backend Service

    Which hash algorithom to choose for new application: https://www.owasp.org/index.php/Password_Storag ...

  2. Android通过startService播放背景音乐简单演示样例

    关于startService的基本使用概述及其生命周期可參见博客<Android中startService的使用及Service生命周期>. 本文通过播放背景音乐的简单演示样例,演示sta ...

  3. js进阶 13-9/10 jquery如何实现三级列表

    js进阶 13-9/10 jquery如何实现三级列表 一.总结 一句话总结:用的是定位,父标签相对定位,子标签就可以绝对定位了,绝对定位的孩子还是可以设置绝对定位.用toggle设置子菜单显示和隐藏 ...

  4. iOS_04_数据类型、常量、变量

    一.数据 1.什么是数据 * 生活中时时刻刻都在跟数据打交道,比如体重数据.血压数据.股价数据等.在我们使用计算机的过程中,会接触到各种各样的数据,有文档数据,图片数据,视频数据,还有聊天QQ产生的文 ...

  5. 通过 Microsoft iSCSI Software Target 提供存储服务

    软件下载地址: Microsoft iSCSI Software Target 3.3 下载完后成解压软件包如下: 安装官方的描述Target 端也就是服务端 只支持Windows Server 20 ...

  6. [Debug] Chrome Devtools: Elements - Console Integration

    The Element Inspector in Chrome DevTools offers powerful integration with the console - learn how to ...

  7. disabled的值无法传递到action层

    假设想让表单不可输入的状态,我将表单设置为了: style="cursor:not-allowed;" disabled 可是这样设置之后就发现,在后台的action怎么都没有办法 ...

  8. [Angular2 Router] Resolving route data in Angular 2

    From Article: RESOLVING ROUTE DATA IN ANGULAR 2 Github If you know Anuglar UI router, you must know ...

  9. pstack.sh 改进版

    pstack.sh 改进版本 #!/bin/bash if (( $# < 1 )) ; then echo "usage: `basename $0` pid" 1> ...

  10. RSA DH

    https://www.cnblogs.com/hiflora/archive/2013/07/04/3171775.html http://www.ruanyifeng.com/blog/2013/ ...