【BZOJ 1023】[SHOI2008]cactus仙人掌图
来源:互联网 发布:剑三捏脸数据 编辑:程序博客网 时间:2024/04/28 01:30
【题目链接】: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仙人掌图
- 【DP】 BZOJ 1023: [SHOI2008]cactus仙人掌图
- bzoj 1023 [SHOI2008]cactus仙人掌图
- 【BZOJ 1023】[SHOI2008]cactus仙人掌图
- bzoj 1023: [SHOI2008]cactus仙人掌图
- bzoj 1023: [SHOI2008]cactus仙人掌图
- BZOJ 1023 SHOI2008 cactus仙人掌图 仙人掌DP
- 1023: [SHOI2008]cactus仙人掌图
- 1023: [SHOI2008]cactus仙人掌图
- [仙人掌直径 单调队列 DP] BZOJ 1023 [SHOI2008]cactus仙人掌图
- 【SHOI2008】【BZOJ1023】cactus仙人掌图
- 【bzoj1023】[SHOI2008]cactus仙人掌图
- bzoj1023: [SHOI2008]cactus仙人掌图
- BZOJ1023 [SHOI2008]cactus仙人掌图
- bzoj1023: [SHOI2008]cactus仙人掌图
- bzoj1023 [SHOI2008]cactus仙人掌图
- BZOJ1023: [SHOI2008]cactus仙人掌图
- 面试题
- Python学习笔记
- 颜色
- 文章标题 UVA 11374 : Airport Express(最短路--dijkstra)
- Android仿微信朋友圈图片展示效果,图片查看器
- 【BZOJ 1023】[SHOI2008]cactus仙人掌图
- QT 动态加载dll
- eclipse+tomcat9 使用多个虚拟域名访问多个web项目
- 纯代码给wordpress增加说说/微博/微语功能
- javamail 发送邮件
- 量化投资-基本面模型-沪铜多因素模型
- 关于迭代器作为模板函数的形参的问题
- 前端基础--浏览器知多少?
- CO07利润中心必输