Loading [MathJax]/extensions/tex2jax.js

「QuestOJ」盛大的庆典 – 题解

主要思路

狗屎状压题。

看到度数不超过 \(10\) 就知道需要状压儿子的信息。考虑处理一个 neck 数组来表示子树内节点到当前子树根下面的节点编号,然后我们每一次往上跳的时候我们都可以对这个数组进行调整,然后 DP 的时候就会比较愉快了。

处理 \(m\) 个请求的时候,我们把对应的 neck 提取出来,然后做标记,按标号小的进行 DP。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// A.cpp
#include <bits/stdc++.h>
using namespace std;
inline char nc()
{
static char buf[1000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
int read()
{
int x = 0, f = 1;
char ch = nc();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = nc();
}
while (isdigit(ch))
x = (x << 3) + (x << 1) + ch - '0', ch = nc();
return x * f;
}
const int MAX_N = 1010, MAX_M = MAX_N * MAX_N;
typedef pair<int, int> pii;
int n, m, mp[MAX_N][20], deg[MAX_N], up[20][MAX_N], dep[MAX_N], chain[MAX_N];
int lft[MAX_N], rig[MAX_N], ptot, anti[MAX_N], dp[MAX_N][1 << 11];
int neck[MAX_N], idx[MAX_N], lg[1 << 11];
vector<int> sid[MAX_N];
vector<pii> requests[20];
struct segment
{
int u, v, d, nu, nv;
} segs[MAX_M];
inline int lowbit(int x) { return x & (-x); }
int getLCA(int x, int y)
{
if (dep[x] < dep[y])
swap(x, y);
for (int i = 19; i >= 0; i--)
if (dep[up[i][x]] >= dep[y])
x = up[i][x];
if (x == y)
return x;
for (int i = 19; i >= 0; i--)
if (up[i][x] != up[i][y])
x = up[i][x], y = up[i][y];
return up[0][x];
}
void dfs(int u, int fa)
{
up[0][u] = fa, dep[u] = dep[fa] + 1;
lft[u] = ++ptot, anti[ptot] = u;
vector<int> sons;
for (int i = 0; i < deg[u]; i++)
if (mp[u][i] != fa)
sons.push_back(mp[u][i]);
deg[u] = sons.size();
for (int i = 0; i < deg[u]; i++)
mp[u][i] = sons[i], idx[mp[u][i]] = i;
for (int i = 0; i < deg[u]; i++)
dfs(mp[u][i], u);
rig[u] = ptot;
}
void collect(int u)
{
for (int i = 0; i < deg[u]; i++)
collect(mp[u][i]);
for (int i = lft[u] + 1; i <= rig[u]; i++)
{
int cpt = anti[i];
if (up[0][cpt] == u)
chain[cpt] += dp[cpt][(1 << deg[cpt]) - 1];
else
{
int cf = up[0][neck[cpt]];
chain[cpt] += dp[cf][(1 << deg[cf]) - 1 - (1 << idx[neck[cpt]])];
neck[cpt] = cf;
}
}
for (int i = 0; i < deg[u]; i++)
idx[mp[u][i]] = i;
for (int i = 0; i < deg[u]; i++)
requests[i].clear();
for (int vid : sid[u])
{
int nu = segs[vid].nu = neck[segs[vid].u], nv = segs[vid].nv = neck[segs[vid].v];
int ndp = chain[segs[vid].u] + chain[segs[vid].v];
if (nu == 0)
swap(nu, nv);
if (nv == 0)
// chain shape;
requests[idx[nu]].push_back(make_pair(ndp, 1 << idx[nu]));
else
{
nu = idx[nu], nv = idx[nv];
if (nu > nv)
swap(nu, nv);
requests[nu].push_back(make_pair(ndp, (1 << nu) | (1 << nv)));
}
}
for (int stat = 1; stat < (1 << deg[u]); stat++)
{
int v = lg[lowbit(stat)];
dp[u][stat] = dp[u][stat ^ (1 << v)] + dp[mp[u][v]][(1 << deg[mp[u][v]]) - 1];
for (auto &g : requests[v])
if ((stat & g.second) == g.second)
dp[u][stat] = max(dp[u][stat], dp[u][stat ^ g.second] + g.first + 1);
}
neck[u] = u;
}
int main()
{
n = read();
for (int i = 1, g; i < (1 << 11); i <<= 1, g++)
lg[i] = g;
for (int i = 1, u, v; i <= n - 1; i++)
u = read(), v = read(), mp[u][deg[u]++] = v, mp[v][deg[v]++] = u;
dfs(1, 0), m = read();
for (int i = 1; i < 20; i++)
for (int j = 1; j <= n; j++)
up[i][j] = up[i - 1][up[i - 1][j]];
for (int i = 1; i <= m; i++)
{
segs[i].u = read(), segs[i].v = read();
segs[i].d = getLCA(segs[i].u, segs[i].v);
sid[segs[i].d].push_back(i);
}
collect(1), printf("%d\n", dp[1][(1 << deg[1]) - 1]);
return 0;
}
// A.cpp #include <bits/stdc++.h> using namespace std; inline char nc() { static char buf[1000000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++; } int read() { int x = 0, f = 1; char ch = nc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = nc(); } while (isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = nc(); return x * f; } const int MAX_N = 1010, MAX_M = MAX_N * MAX_N; typedef pair<int, int> pii; int n, m, mp[MAX_N][20], deg[MAX_N], up[20][MAX_N], dep[MAX_N], chain[MAX_N]; int lft[MAX_N], rig[MAX_N], ptot, anti[MAX_N], dp[MAX_N][1 << 11]; int neck[MAX_N], idx[MAX_N], lg[1 << 11]; vector<int> sid[MAX_N]; vector<pii> requests[20]; struct segment { int u, v, d, nu, nv; } segs[MAX_M]; inline int lowbit(int x) { return x & (-x); } int getLCA(int x, int y) { if (dep[x] < dep[y]) swap(x, y); for (int i = 19; i >= 0; i--) if (dep[up[i][x]] >= dep[y]) x = up[i][x]; if (x == y) return x; for (int i = 19; i >= 0; i--) if (up[i][x] != up[i][y]) x = up[i][x], y = up[i][y]; return up[0][x]; } void dfs(int u, int fa) { up[0][u] = fa, dep[u] = dep[fa] + 1; lft[u] = ++ptot, anti[ptot] = u; vector<int> sons; for (int i = 0; i < deg[u]; i++) if (mp[u][i] != fa) sons.push_back(mp[u][i]); deg[u] = sons.size(); for (int i = 0; i < deg[u]; i++) mp[u][i] = sons[i], idx[mp[u][i]] = i; for (int i = 0; i < deg[u]; i++) dfs(mp[u][i], u); rig[u] = ptot; } void collect(int u) { for (int i = 0; i < deg[u]; i++) collect(mp[u][i]); for (int i = lft[u] + 1; i <= rig[u]; i++) { int cpt = anti[i]; if (up[0][cpt] == u) chain[cpt] += dp[cpt][(1 << deg[cpt]) - 1]; else { int cf = up[0][neck[cpt]]; chain[cpt] += dp[cf][(1 << deg[cf]) - 1 - (1 << idx[neck[cpt]])]; neck[cpt] = cf; } } for (int i = 0; i < deg[u]; i++) idx[mp[u][i]] = i; for (int i = 0; i < deg[u]; i++) requests[i].clear(); for (int vid : sid[u]) { int nu = segs[vid].nu = neck[segs[vid].u], nv = segs[vid].nv = neck[segs[vid].v]; int ndp = chain[segs[vid].u] + chain[segs[vid].v]; if (nu == 0) swap(nu, nv); if (nv == 0) // chain shape; requests[idx[nu]].push_back(make_pair(ndp, 1 << idx[nu])); else { nu = idx[nu], nv = idx[nv]; if (nu > nv) swap(nu, nv); requests[nu].push_back(make_pair(ndp, (1 << nu) | (1 << nv))); } } for (int stat = 1; stat < (1 << deg[u]); stat++) { int v = lg[lowbit(stat)]; dp[u][stat] = dp[u][stat ^ (1 << v)] + dp[mp[u][v]][(1 << deg[mp[u][v]]) - 1]; for (auto &g : requests[v]) if ((stat & g.second) == g.second) dp[u][stat] = max(dp[u][stat], dp[u][stat ^ g.second] + g.first + 1); } neck[u] = u; } int main() { n = read(); for (int i = 1, g; i < (1 << 11); i <<= 1, g++) lg[i] = g; for (int i = 1, u, v; i <= n - 1; i++) u = read(), v = read(), mp[u][deg[u]++] = v, mp[v][deg[v]++] = u; dfs(1, 0), m = read(); for (int i = 1; i < 20; i++) for (int j = 1; j <= n; j++) up[i][j] = up[i - 1][up[i - 1][j]]; for (int i = 1; i <= m; i++) { segs[i].u = read(), segs[i].v = read(); segs[i].d = getLCA(segs[i].u, segs[i].v); sid[segs[i].d].push_back(i); } collect(1), printf("%d\n", dp[1][(1 << deg[1]) - 1]); return 0; }
// A.cpp
#include <bits/stdc++.h>

using namespace std;

inline char nc()
{
    static char buf[1000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}

int read()
{
    int x = 0, f = 1;
    char ch = nc();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = nc();
    }
    while (isdigit(ch))
        x = (x << 3) + (x << 1) + ch - '0', ch = nc();
    return x * f;
}

const int MAX_N = 1010, MAX_M = MAX_N * MAX_N;

typedef pair<int, int> pii;

int n, m, mp[MAX_N][20], deg[MAX_N], up[20][MAX_N], dep[MAX_N], chain[MAX_N];
int lft[MAX_N], rig[MAX_N], ptot, anti[MAX_N], dp[MAX_N][1 << 11];
int neck[MAX_N], idx[MAX_N], lg[1 << 11];
vector<int> sid[MAX_N];
vector<pii> requests[20];

struct segment
{
    int u, v, d, nu, nv;
} segs[MAX_M];

inline int lowbit(int x) { return x & (-x); }

int getLCA(int x, int y)
{
    if (dep[x] < dep[y])
        swap(x, y);
    for (int i = 19; i >= 0; i--)
        if (dep[up[i][x]] >= dep[y])
            x = up[i][x];
    if (x == y)
        return x;
    for (int i = 19; i >= 0; i--)
        if (up[i][x] != up[i][y])
            x = up[i][x], y = up[i][y];
    return up[0][x];
}

void dfs(int u, int fa)
{
    up[0][u] = fa, dep[u] = dep[fa] + 1;
    lft[u] = ++ptot, anti[ptot] = u;
    vector<int> sons;
    for (int i = 0; i < deg[u]; i++)
        if (mp[u][i] != fa)
            sons.push_back(mp[u][i]);
    deg[u] = sons.size();
    for (int i = 0; i < deg[u]; i++)
        mp[u][i] = sons[i], idx[mp[u][i]] = i;
    for (int i = 0; i < deg[u]; i++)
        dfs(mp[u][i], u);
    rig[u] = ptot;
}

void collect(int u)
{
    for (int i = 0; i < deg[u]; i++)
        collect(mp[u][i]);
    for (int i = lft[u] + 1; i <= rig[u]; i++)
    {
        int cpt = anti[i];
        if (up[0][cpt] == u)
            chain[cpt] += dp[cpt][(1 << deg[cpt]) - 1];
        else
        {
            int cf = up[0][neck[cpt]];
            chain[cpt] += dp[cf][(1 << deg[cf]) - 1 - (1 << idx[neck[cpt]])];
            neck[cpt] = cf;
        }
    }
    for (int i = 0; i < deg[u]; i++)
        idx[mp[u][i]] = i;
    for (int i = 0; i < deg[u]; i++)
        requests[i].clear();
    for (int vid : sid[u])
    {
        int nu = segs[vid].nu = neck[segs[vid].u], nv = segs[vid].nv = neck[segs[vid].v];
        int ndp = chain[segs[vid].u] + chain[segs[vid].v];
        if (nu == 0)
            swap(nu, nv);
        if (nv == 0)
            // chain shape;
            requests[idx[nu]].push_back(make_pair(ndp, 1 << idx[nu]));
        else
        {
            nu = idx[nu], nv = idx[nv];
            if (nu > nv)
                swap(nu, nv);
            requests[nu].push_back(make_pair(ndp, (1 << nu) | (1 << nv)));
        }
    }
    for (int stat = 1; stat < (1 << deg[u]); stat++)
    {
        int v = lg[lowbit(stat)];
        dp[u][stat] = dp[u][stat ^ (1 << v)] + dp[mp[u][v]][(1 << deg[mp[u][v]]) - 1];
        for (auto &g : requests[v])
            if ((stat & g.second) == g.second)
                dp[u][stat] = max(dp[u][stat], dp[u][stat ^ g.second] + g.first + 1);
    }
    neck[u] = u;
}

int main()
{
    n = read();
    for (int i = 1, g; i < (1 << 11); i <<= 1, g++)
        lg[i] = g;
    for (int i = 1, u, v; i <= n - 1; i++)
        u = read(), v = read(), mp[u][deg[u]++] = v, mp[v][deg[v]++] = u;
    dfs(1, 0), m = read();
    for (int i = 1; i < 20; i++)
        for (int j = 1; j <= n; j++)
            up[i][j] = up[i - 1][up[i - 1][j]];
    for (int i = 1; i <= m; i++)
    {
        segs[i].u = read(), segs[i].v = read();
        segs[i].d = getLCA(segs[i].u, segs[i].v);
        sid[segs[i].d].push_back(i);
    }
    collect(1), printf("%d\n", dp[1][(1 << deg[1]) - 1]);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *