【BZOJ 1023】[SHOI2008]cactus仙人掌图
【题目链接】: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仙人掌图的更多相关文章
- bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列
1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 1141 Solved: 435[Submit][ ...
- 【刷题】BZOJ 1023 [SHOI2008]cactus仙人掌图
Description 如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人掌图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的 ...
- BZOJ 1023: [SHOI2008]cactus仙人掌图 | 在仙人掌上跑DP
题目: 求仙人掌直径 http://www.lydsy.com/JudgeOnline/problem.php?id=1023 题解: 首先给出仙人掌的定义:满足所有的边至多在一个环上的无向联通图 我 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图 2125: 最短路 4728: 挪威的森林 静态仙人掌上路径长度的维护系列
%%% http://immortalco.blog.uoj.ac/blog/1955 一个通用的写法是建树,对每个环建一个新点,去掉环上的边,原先环上每个点到新点连边,边权为点到环根的最短/长路长度 ...
- bzoj 1023 [SHOI2008]cactus仙人掌图 ( poj 3567 Cactus Reloaded )——仙人掌直径模板
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1023 http://poj.org/problem?id=3567 因为lyd在讲课,所以有 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图
这道题是我做的第一道仙人掌DP,小小纪念一下…… 仙人掌DP就是环上的点环状DP,树上的点树上DP.就是说,做一遍DFS,DFS的过程中处理出环,环上的点先不DP,先把这些换上的点的后继点都处理出来, ...
- BZOJ.1023.[SHOI2008]cactus仙人掌图(DP)
题目链接 类似求树的直径,可以用(类似)树形DP求每个点其子树(在仙人掌上就是诱导子图)最长链.次长链,用每个点子节点不同子树的 max{最长链}+max{次长链} 更新答案.(不需要存次长链,求解过 ...
- bzoj 1023: [SHOI2008]cactus仙人掌图【tarjan+dp+单调队列】
本来想先求出点双再一个一个处理结果写了很长发现太麻烦 设f[u]为u点向下的最长链 就是再tarjan的过程中,先照常处理,用最长儿子链和次长儿子链更新按ans,然后处理以这个点为根的环,也就是这个点 ...
- 1023: [SHOI2008]cactus仙人掌图 - BZOJ
Description如果某个无向连通图的任意一条边至多只出现在一条简单回路(simple cycle)里,我们就称这张图为仙人图(cactus).所谓简单回路就是指在图上不重复经过任何一个顶点的回路 ...
- 【BZOJ】1023: [SHOI2008]cactus仙人掌图 静态仙人掌(DFS树)
[题意]给定仙人掌图(每条边至多在一个简单环上),求直径(最长的点对最短路径).n<=50000,m<=10^7. [算法]DFS树处理仙人掌 [题解]参考:仙人掌相关问题的处理方法(未完 ...
随机推荐
- 关于CSDN2013博客之星的一些看法
最近一个周,最火的话题当然要数CSDN2013博客之星拉票了. 实话实说,从12月14日开始,我连续5天拉票. 通过QQ群.QQ好友.CSDN文章.给CSDN粉丝发私信等多种方式拉票,真是累死我了. ...
- Request、Response 之 Http 请求
今天说些什么呢? 说说Request吧! Request是什么: 请求(Request):一个从客户端到服务器的请求信息包括应用于资源的方法.资源的标识符和协议的版本号 request这个对象不用事先 ...
- [React] Theme your application with styled-components and "ThemeProvider"
In this styled-components lesson, we set a "primary color" within a UI "theme" o ...
- 用多年前据说买买提上理论水平最高的帖子做镇楼贴---NASA有吹牛了
美国国会一直有意把nasa 划入国防部,取消太空探索所关联的部门,因为这些部门都是些烧钱的大包袱,而把具有军事意义的部门留下.国会想把烧钱部卖给google,可能是要价太高,最后没有谈拢,不了了之.但 ...
- MySql基本的语法(学习笔记)
MySQL语法大全_自己整理的学习笔记 select * from emp; #凝视 #--------------------------- #----命令行连接MySql--------- #启 ...
- 9.2 Binder系统_驱动情景分析_服务注册过程
1. 几个重要结构体的引入给test_server添加一个goodbye服务, 由此引入以下概念: 进程间通信其实质也是需要三要素:源.目的.数据,源是自己,目的用handle表示:通讯的过程是源向实 ...
- 【习题 5-11 UVA 12504 】Updating a Dictionary
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 不确定某个map里面是否有某个关键字的时候. 要用find来确定. 如果直接用访问下标的形式去做的话. 会强行给他加一个那个关键字( ...
- python课程:python3的输入输出
输出函数用法 (话说python3的输出好像没有python2的灵活了) print('hello,world') #单引号和双引号都可以输出print("hello,world&quo ...
- DateTime与timeStamp的转换
DateTime转换为timeStamp: DateTime dt = DateTime.Now; DateTime startTime = TimeZone.CurrentTi ...
- arm Linux 如何自动检测并mount SD卡,以及如何得知已经mount
一.土八路做法: SD 卡一旦插入系统,内核会自动在/dev/下创建设备文件:sdcard. 但有时可能时用户在拨出卡前并没有umount的话,第二次插卡进去后系统创建的就不是sdcard设备文件了, ...