[BZOJ1023][SHOI2008[Cactus仙人掌]][Tarjan+单调队列+树形DP]
[BZOJ1023][SHOI2008[Cactus仙人掌]][Tarjan+单调队列+树形DP]
题目大意:
给定一棵仙人掌,求仙人掌上最长路径。(路径要求是两点之间的最短路)
思路:
题目太神啦
好菜啊虽然过了BZOJ1040但还是一点不会做,快来看这个题解太神啦:http://z55250825.blog.163.com/blog/static/150230809201412793151890/
代码:
#include <bits/stdc++.h> const int Maxn = 100010; using namespace std; inline int Max(const int &a, const int &b) { return a > b ? a : b; } inline int Min(const int &a, const int &b) { return a < b ? a : b; } namespace IO { inline char get(void) { static char buf[1000000], *p1 = buf, *p2 = buf; if (p1 == p2) { p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin); if (p1 == p2) return EOF; } return *p1++; } inline void read(int &x) { x = 0; static char c; for (; !(c >= '0' && c <= '9'); c = get()); for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get()); } }; int head[Maxn], sub; struct Edge { int to, nxt; Edge(void) {} Edge(const int &to, const int &nxt) : to(to), nxt(nxt) {} } edge[20000005]; inline void add(int a, int b) { edge[++sub] = Edge(b, head[a]), head[a] = sub; } int n, m; int fa[Maxn], low[Maxn], dfn[Maxn], FFF, dep[Maxn], f[Maxn], ans; int a[Maxn], q[Maxn], l, r; inline void Dp(int u, int v) { int tot = dep[v] - dep[u] + 1; for (int i = v; i != u; i = fa[i]) { a[tot--] = f[i]; } a[tot] = f[u]; tot = dep[v] - dep[u] + 1; for (int i = 1; i <= tot; i++) a[i + tot] = a[i]; q[1] = 1; l = r = 1; for (int i = 2; i <= tot << 1; i++) { while (l <= r && i - q[l] > tot / 2) l++; ans = Max(ans, a[i] + i + a[q[l]] - q[l]); while (l <= r && a[q[r]] - q[r] <= a[i] - i) r--; q[++r] = i; } for (int i = 2; i <= tot; i++) f[u] = Max(f[u], a[i] + Min(i - 1, tot - i + 1)); } inline void dfs(int u) { low[u] = dfn[u] = ++FFF; for (int i = head[u], v; i; i = edge[i].nxt) { v = edge[i].to; if (v == fa[u]) continue; if (!dfn[v]) { fa[v] = u; dep[v] = dep[u] + 1; dfs(v); low[u] = Min(low[u], low[v]); } else low[u] = Min(low[u], dfn[v]); if (dfn[u] < low[v]) { ans = Max(ans, f[u] + f[v] + 1); f[u] = Max(f[u], f[v] + 1); } } for (int i = head[u], v; i; i = edge[i].nxt) { v = edge[i].to; if (fa[v] != u && dfn[u] < dfn[v]) Dp(u, v); } } int main(void) { //freopen("in.txt", "r", stdin); IO::read(n); IO::read(m); int k, a, b; for (int i = 1; i <= m; i++) { IO::read(k), IO::read(a); for (int j = 2; j <= k; j++) { IO::read(b); add(a, b), add(b, a); a = b; } } dfs(1); cout << ans << endl; return 0; }完。
By g1n0st