【题目链接】: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. OpenCV func

    cvLoadImage("lena.jpg", CV_LOAD_IMAGE_COLOR);  //CV_LOAD_IMAGE_GRAYSCALE   //0

  2. POJ 3723 Conscription MST

    http://poj.org/problem?id=3723 题目大意: 需要征募女兵N人,男兵M人,没征募一个人需要花费10000美元,但是如果已经征募的人中有一些关系亲密的人,那么可以少花一些钱, ...

  3. 苹果手机wifi代理设置方法--用于抓包

    杯具了!@@@@@@@变态的公司不能直接上网了,但是经过我的研究.可以用代理上网,电脑是可以了,但是的iphone肿么办,哇咔咔,不要捉急,我来告诉你怎么让你的iphone通过代理上网.动起来吧. 请 ...

  4. 详解Spring Boot配置文件之多环境配置

    一. 多环境配置的好处: 1.不同环境配置可以配置不同的参数~ 2.便于部署,提高效率,减少出错~ 二. properties多环境配置 1. 配置激活选项 spring.profiles.activ ...

  5. Java BigDecimal的基本使用方法

    1.对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类 2.运算速度比一般的+.-.*./要快 3.基本方 法描 述  ...

  6. git 配置用户名email地址,设置密码

  7. 自己定义Dialog的具体步骤(实现自己定义样式一般原理)

    转载请标注转载http://blog.csdn.net/oqihaogongyuan/article/details/50958659 自己定义Dialog的具体步骤(实现自己定义样式一般原理)    ...

  8. UILabel基本用法

    UILabel *_label = [[UILabel alloc]initWithFrame:CGRectMake(, self.view.frame.size.height*)]; _label. ...

  9. ng build --base-href的设定问题

    项目构建部署中遇到的问题: 1.不使用hash,如何解决刷新页面404的问题? 说明: root  指定项目地址路径,默认为nginx下的html index  默认访问index文件 try_fil ...

  10. arm-linux-gcc: Command not found

    老是提示arm-linux-gcc找不到,但是确实是装好了,其实是权限的问题,Ubuntu没有root权限,刚开始用碰到很多麻烦,查了好多资料,终于把arm-linux-gcc: Command no ...