XSY2444 BZOJ4042 [] [] [] [luogu4757 CERC2014] Parades (tree-like pressure dp + dp)

Face questions

Description

There was once a CJB country, it has \ (n \) cities and \ (n-1 \) path. Every road connecting the two cities. Twenty-two between the city up. Each city is connected to no more than 10 roads.

HZ national leaders to visit the country since CJB country, CJB wanted to parade past as HZ. CJB planned \ (m \) route. Route \ (I \) from \ (u_i \) to \ (V_I \) is the shortest path.

You are the Chairman of the Central Military Commission CJB country, you need to ensure national security. Therefore, the official parade, any two lines can not intersect (In this problem, refer to the intersection after a common path, that is the only common city route not intersect).

Because CJB love HZ, so he wants you to this \ (m \) route, select as many routes as an official parade route, so that these routes mutually disjoint.

Input

The first line of input test data set number \ (T \) .

For each set of test data:

The first line an integer \ (the n-(2≤n≤1000) \) , represents the number of cities.

Next \ (n-1 \) lines of two integers \ (A, b (1 ≤ a ≠ b≤n) \) , represents the city \ (a \) and \ (b \) there is a road. Each city is connected to a maximum of 10 roads.

Next, an integer \ (m (0≤m≤ \ {n-FRAC (. 1-n-)} {2}) \) .

Next \ (m \) lines of two integers \ (u_i \) , \ (V_I (1≤ui ≠ vi≤n) \) , represented CJB Programming \ (m \) routes.

Output

For each test, the maximum number of integer output a formal parade route.

Sample Input

1
6
1 2
2 3
3 4
3 5
3 6
4
1 3
4 5
5 6
6 4

Sample Output

2

HINT

Sample interpretation

Select \ ((1,3) \) , \ ((4,5) \)

data range

Note \ (\ sum {n} \ ) of all \ (T \) set of test data \ (n-\) combined.

For \ (10 \% \) data, \ (2≤n≤50 \) , \ (1≤m≤20 \) , \ (T≤4 \)

For \ (40 \% \) data, \ (2≤n≤50 \) , \ (\ {n-SUM ≤3600} \) , \ (T ≦ 100 \)

For all data, \ (2≤n≤1000 \) , \ (\ {n-SUM ≤18000} \) , \ (T ≦ 100 \)

answer

Consider the tree \ (DP \) , provided \ (dp [i] \) represented by \ (I \) the maximum number (i.e., optimal solution subtree tree) in the subtree rooted route, \ (UN [ I] [] \) represented by \ (I \) is the subtree rooted at all points \ (U \) , if and only if \ (I \) to \ (U \) on the path does not \ (I \) optimal solution subtree of a path intersect.

Then consider merging sub-tree root.

For \ (dp [U] \) , we first add each son \ (dp \) value, then we will consider the following two cases:

  1. For \ (U \) of one son \ (Son \) , if the \ (Son \) within the sub-tree (including \ (Son \) themselves) have a point \ (v = un [son] [i] \ ) and \ (U \) there is a path between \ ((U, V) \) , as shown:

    Here Insert Picture Description
    Possible for one son \ (Son \) , this path may have a lot of pieces, but can choose any one, because the edge \ ((u, v) \ ) can only go again.

  2. For \ (U \) in a different two sons \ (son_1 \) , \ (son_2 \) , each of which the sub-tree (including \ (son_1 \) , \ (son_2 \) ) are two points \ (A UN = [son_1] [I] \) , \ (B UN = [son_2] [J] \) , and there is a path \ ((A, B) \) , we put \ (link [son_1] [son_2] \) is set to \ (1 \) , as shown:

    Here Insert Picture Description
    So for a son \ (son_1 \) , it may be matched to a number \ (son_2 \) , so how to choose the best program it is the key to solve the problem, so we like to consider pressing \ (dp \) .

    Set \ (f [i] \) shows a state \ (I \) is the optimal solution, the state \ (I \) of a binary expression \ (X \) byte to \ (1 \) , then have consider the case of the addition of this son.

    So we have small to large enumeration \ (i \) , find \ (A = \ _ \ _ the BUILTIN \ _ctz (i) \) , \ (LB = lowbit (i) \) , then \ (i \) from \ (i-lb \) transferred from, as in \ (i-lb \) of the binary representation, the first \ (a \) bit \ (0 \) ; in \ (I \) binary expression, The first \ (A \) bit \ (1 \) .

    So now we consider is considering adding his son \ (A \) , which is above \ (son_1 \) , then we have to enumerate \ (son_2 \) , that is, below \ (b \) .

    For each \ (B \) , when the \ (link (a, b) = 1 \) and \ (I \) binary expression of \ (B \) bit \ (1 \) , we get :

    \[f[i]=max(f[i],f[i-(1<<a)-(1<<b)]+1)\]

    I.e. from \ (I \) of \ (A \) bit \ (0 \) and the first \ (B \) bit \ (0 \) transferred over time.

    Finally \ (dp [u] + = f [2 ^ {u \ son number of text {}} - 1] \) to.

This merger is complete.

Remember to maintain it after the merger \ (un [U] \) .

Finally, output \ (dp [1] \) alone.

The complete code annotated as follows:

#include<bits/stdc++.h>
 
#define N 1010
#define D 15
 
using namespace std;
 
int T,n,m;
int dp[N],f[1<<D];
int cnt,head[N],nxt[N<<1],to[N<<1];
bool vis[N][N],link[D][D];
 
vector<int>un[N];
 
int lowbit(int x)
{
    return x&-x;
}
 
void init()
{
    cnt=0;
    memset(head,0,sizeof(head));
    memset(vis,false,sizeof(vis));
    memset(dp,0,sizeof(dp));
}
 
void adde(int u,int v)
{
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
 
void dfs(int u,int fa)
{
    int son[D],tot=0;
    for(int i=head[u];i;i=nxt[i])
    {
        if(to[i]!=fa)
        {
            dfs(to[i],u);
            dp[u]+=dp[to[i]];
            son[tot++]=to[i];   //存储每一个儿子
        }
    }
    for(int i=0;i<tot;i++)
    {
        for(int j=0;j<un[son[i]].size();j++)
        {
            if(vis[un[son[i]][j]][u])   
            {
                dp[u]++;
                un[son[i]].clear();//由于已经选了一条边了,所以为了下面的维护un[u],我们把un[son[i]]清零
            }       
        }
    }
    memset(link,false,sizeof(link));
    for(int i=0;i<tot;i++)
    {
        for(int j=i+1;j<tot;j++)
        {
            int a=son[i],b=son[j];
            for(int p=0;p<un[a].size();p++)
            {
                for(int q=0;q<un[b].size();q++)
                {
                    if(vis[un[a][p]][un[b][q]])
                    {
                        link[i][j]=link[j][i]=true;//标记son[i]与son[j]各自子树之间有路径
                        break;
                    }
                }
                if(link[i][j])
                    break;
            }
        }   
    }
    f[0]=0;
    int maxn=(1<<tot)-1;
    for(int i=1;i<=maxn;i++)
    {
        f[i]=f[i-lowbit(i)];
        int a=__builtin_ctz(i);
        for(int b=a+1;b<tot;b++)//枚举son2
            if(link[a][b]&&((i>>b)&1))
                f[i]=max(f[i],f[i-(1<<a)-(1<<b)]+1);
    }
    dp[u]+=f[maxn];
    un[u].push_back(u);
    for(int i=0;i<tot;i++)
        if(f[maxn]==f[maxn-(1<<i)])
            for(int j=0;j<un[son[i]].size();j++)
                un[u].push_back(un[son[i]][j]);//维护un[u]
}
 
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            un[i].clear();
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            adde(u,v),adde(v,u);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            vis[u][v]=vis[v][u]=true;
        }
        dfs(1,0);
        printf("%d\n",dp[1]);
    }
}

Guess you like

Origin www.cnblogs.com/ez-lcw/p/11520249.html