[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