【BZOJ 1023】【SHOI 2008】cactus仙人掌图
2016-05-18 20:50
316 查看
良心的题解↓
http://z55250825.blog.163.com/blog/static/150230809201412793151890/
tarjan的时候如果是树边则做树形DP(遇到环就无视),最后在tarjan回溯前扫一遍当前点为“最高点”的环,进行环上DP,这个环上DP是$O(n^2)$的,但如果我们用单调队列优化则是$O(n)$的
总复杂度$O(n)$真是无限仰膜OTZ
仙人掌虽然偏,但是不知道也不可以,这个代码是我磕了一晚上题解的成果QAQ
http://z55250825.blog.163.com/blog/static/150230809201412793151890/
tarjan的时候如果是树边则做树形DP(遇到环就无视),最后在tarjan回溯前扫一遍当前点为“最高点”的环,进行环上DP,这个环上DP是$O(n^2)$的,但如果我们用单调队列优化则是$O(n)$的
总复杂度$O(n)$真是无限仰膜OTZ
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 500003; void read(int &k) { k = 0; int fh = 1; char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) if (c == '-') fh = -1; for(; c >= '0' && c <= '9'; c = getchar()) k = (k << 1) + (k << 3) + c - '0'; k = k * fh; } struct node {int nxt, to;} E[N << 1]; int ans = 0, point , n, m, cnt = 0, l, r; int deep , F , fa , DFN , low , Q[N << 1], tb[N << 1]; void ins(int x, int y) {E[++cnt] = (node) {point[x], y}; point[x] = cnt;} void __(int rt, int x) { int tot = deep[x] - deep[rt] + 1, num = tot << 1, top = tot >> 1; for(int tmp = x; tmp != rt; tmp = fa[tmp]) tb[tot--] = F[tmp]; tb[1] = F[rt]; tot = deep[x] - deep[rt] + 1; for(int i = 1; i <= tot; ++i) tb[tot + i] = tb[i]; l = r = 1; Q[1] = 1; for(int i = 2; i <= num; ++i) { while (l <= r && i - Q[l] > top) ++l; ans = max(ans, tb[i] + i + tb[Q[l]] - Q[l]); while (l <= r && tb[Q[r]] - Q[r] <= tb[i] - i) --r; Q[++r] = i; } for(int i = 2; i <= tot; ++i) F[rt] = max(F[rt], tb[i] + min(i - 1, tot - i + 1)); } void _(int x) { DFN[x] = low[x] = ++cnt; for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) { int v = E[tmp].to; if (v == fa[x]) continue; if (!DFN[v]) { fa[v] = x; deep[v] = deep[x] + 1; _(v); low[x] = min(low[x], low[v]); } else low[x] = min(low[x], DFN[v]); if (DFN[x] < low[v]) { ans = max(ans, F[x] + F[v] + 1); F[x] = max(F[x], F[v] + 1); } } for(int tmp = point[x]; tmp; tmp = E[tmp].nxt) { int v = E[tmp].to; if (x == fa[v] || DFN[x] > DFN[v]) continue; __(x, v); } } int main() { read(n); read(m); int u, v, k; for(int i = 1; i <= m; ++i) { read(k); read(u); for(--k; k; --k) {read(v); ins(u, v); ins(v, u); u = v;} } cnt = 0; _(1); printf("%d\n", ans); return 0; }
仙人掌虽然偏,但是不知道也不可以,这个代码是我磕了一晚上题解的成果QAQ
相关文章推荐
- linux之批量替换多个文件中相同的字符串
- php抽象类
- 【HTML】——总结-实践框架、表单、表格
- Linux下发布QT程序
- Jsoup 教程
- 侧滑
- Context都没弄明白,还怎么做Android开发?
- leetcode
- 数组作数据成员
- putty 背景透明度设置及使用技巧
- Android 微信摇一摇记录摇的次数
- 推荐系统实践笔记--1
- 如何使用 PsExec 执行远程命令
- 前端资源简单整理下
- ClassNotFoundException: org.codehaus.xfire.transport.http.XFireConfigurableServlet怎么解决
- 1.关系性数据库及SQL
- 【C++】:C++函数重载的映射机制(内容较深)
- iptables + Denyhost抵御暴力破解
- leiningen构建工具的project.clj配置
- iOS组件之UILabel