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;
}