BZOJ 4042 Luogu P4757 [CERC2014] Parades (tree DP, like pressure DP)

Topic Link

(BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4042
(Luogu) https://www.luogu.org/problem/P4757

answer

Very fairy theme.
We observed two important properties:

(1) Only the selected program does not affect any of the time, only need to consider whether you want to select (u \) \ to go up in the subtree chain. (Since weights without chain)

(2) If you want to select \ (u \) to go up the chain within the sub-tree, then select up to a.

It can be seen, we can record what chain \ (u \) of all programs in the sub-tree is mandatory that all non-mandatory are regarded idle. Because going up the chain up to a choice, so if this chain and a non-mandatory side of the conflict, there are ways to adjust the optimal solution makes this option chains, without being "non-mandatory two sides at least choose a "impact of this situation.

So we record \ (dp [u] \) represents \ (U \) within a sub-tree and select the maximum number of chain \ (S [u] \) represents \ (U \) optimal solution be optionally endpoints within subtree , when transferred to first take out all sons, building a graph, two \ (i, j \) connected if and only if the presence of edge \ (x \ in S [i ], y \ in S [j], x, y \) is an input path, and then to find its maximum matching shape with pressure DP. Set \ (dp0 [i] \) represents \ (I \) maximum matching within the set, \ (the U-\) for all sons repertoire then if \ (dp0 [U] = dp0 [U - \ {i \} ] \) to illustrate \ (I \) non-mandatory, then the \ (S [i] \) was added to the \ (S [u] \) in.
Note that special handling to \ (U \) for the case where a chain end.

Time complexity \ (O (n-2 ^ + D ^ + ND2 m) \) .

Code

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
#include<vector>
using namespace std;

const int N = 1000;
const int M = 5e5;
const int D = 10;
int lg2[(1<<D)+3];
struct Edge
{
    int v,nxt;
} e[(N<<1)+3];
int fe[N+3];
int fa[N+3];
bool a[N+3][N+3];
vector<int> ac[N+3];
int dp[N+3];
vector<int> son;
bool ae[D+3][D+3];
bool ae0[D+3];
int dp0[(1<<D)+3];
int n,en,m;

void addedge(int u,int v)
{
    en++; e[en].v = v;
    e[en].nxt = fe[u]; fe[u] = en;
}

void dfs(int u)
{
    dp[u] = 0;
    for(int i=fe[u]; i; i=e[i].nxt)
    {
        int v = e[i].v;
        if(v==fa[u]) continue;
        fa[v] = u;
        dfs(v);
        dp[u] += dp[v];
    }
    son.clear();
    for(int i=fe[u]; i; i=e[i].nxt)
    {
        int v = e[i].v;
        if(v==fa[u]) continue;
        son.push_back(v);
    }
    for(int i=0; i<son.size(); i++)
    {
        for(int j=i+1; j<son.size(); j++)
        {
            ae[i][j] = ae[j][i] = false;
            for(int ii=0; ii<ac[son[i]].size(); ii++)
            {
                for(int jj=0; jj<ac[son[j]].size(); jj++)
                {
                    if(a[ac[son[i]][ii]][ac[son[j]][jj]])
                    {
                        ae[i][j] = ae[j][i] = true; break;
                    }
                }
            }
        }
        ae0[i] = false;
        for(int ii=0; ii<ac[son[i]].size(); ii++) {if(a[ac[son[i]][ii]][u]) {ae0[i] = true; break;}}
    }
    dp0[0] = 0;
    for(int i=1; i<(1<<son.size()); i++)
    {
        int x = lg2[i&(-i)];
        dp0[i] = dp0[i^(1<<x)];
        if(ae0[x]) {dp0[i]++;}
        for(int j=0; j<son.size(); j++)
        {
            if(i&(1<<j))
            {
                if(ae[x][j]) {dp0[i] = max(dp0[i],dp0[i^(1<<x)^(1<<j)]+1);}
            }
        }
    }
    dp[u] += dp0[(1<<son.size())-1];
    for(int i=0; i<son.size(); i++)
    {
        if(dp0[(1<<son.size())-1]==dp0[((1<<son.size())-1)^(1<<i)])
        {
            for(int j=0; j<ac[son[i]].size(); j++) {ac[u].push_back(ac[son[i]][j]);}
        }
    }
    ac[u].push_back(u);
}

int main()
{
    for(int i=0; i<=D; i++) lg2[1<<i] = i;
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1; i<n; i++)
        {
            int u,v; scanf("%d%d",&u,&v);
            addedge(u,v); addedge(v,u);
        }
        scanf("%d",&m);
        for(int i=1; i<=m; i++)
        {
            int u,v; scanf("%d%d",&u,&v);
            a[u][v] = a[v][u] = 1;
        }
        dfs(1);
        printf("%d\n",dp[1]);
        for(int i=1; i<=n; i++) fe[i] = fa[i] = 0,ac[i].clear();
        for(int i=1; i<=en; i++) e[i].v = e[i].nxt = 0;
        for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j] = a[j][i] = 0;
        n = en = m = 0;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11491120.html