A small tree of the problem solution bzoj5072

The meaning of problems

Gives a tree of n points, each point in black or white. q interrogation times, each
query given x and y, and asked whether to select a link subgraph points x, such that where
the number of black dots to y.

range

n ≤ 5000,q ≤ 10^5

In fact, I would not have to proveDid not understandJust listening to the teacher, we can guess: For connected subgraphs of a certain size, which contains the number of all points between the minimum and maximum number of black dots are able to get to.

Proof: proved to be very simple, from the viewpoint of the minimum point and add one point to remove the maximum over-
drive up the number of black spots change every time 1, it is possible to traverse from the minimum to the maximum value in
all points. (From dzy)

We define F [x] [y] to x rooted tree of nodes that has the least number of black dots y

Similarly G [x] [y] to x tree root nodes maximum black dots y

Then this problem will be resolved tree backpack, time complexity (n ^ 2)

Code

#include<bits/stdc++.h>
using namespace std;
const int Max=5010;
int n,T,q,tot,u,v,root,xi,yi;
int ver[Max*2],head[Max],Next[Max*2];
int score[Max];
int f[Max][Max],g[Max][Max],siz[Max],ff[Max],gg[Max];
void add(int x,int y){ 
    ver[++tot]=y;Next[tot]=head[x];head[x]=tot;
}
void dp(int x,int fa){//由于存树时用的是双向图,此处要判断 
    siz[x]=1;
    g[x][score[x]]=1;//初始化保证g[x][0] or f[x][0]为1,否则最小值永远是0 
    f[x][score[x]]=1;
    for(int i=head[x];i;i=Next[i]){
        int y=ver[i];
        if(fa==y) continue;
        dp(y,x);
        memcpy(ff,f[x],sizeof f[x]);//由于在进行背包的过程中求得的不一定是最优解,故用临时数组进行储存 
        memcpy(gg,g[x],sizeof g[x]);
        for(int t=siz[x];t>=score[x];--t){//两棵树的合并 
            for(int j=siz[y];j>=score[y];--j){
                ff[t+j]=min(ff[t+j],f[x][t]+f[y][j]);
                gg[t+j]=max(gg[t+j],g[x][t]+g[y][j]);
            }
        }
        siz[x]+=siz[y];
        for(int j=score[x];j<=siz[x];++j){
            f[x][j]=ff[j];
            g[x][j]=gg[j];
        }   
    }
    for(int i=0;i<=siz[x];++i){//用g[0][x] f[0][x]储存答案 
        f[0][i]=min(f[0][i],f[x][i]);
        g[0][i]=max(g[0][i],g[x][i]);
    }
    return;
}
int main(){
    //freopen("trees.in","r",stdin);
    //freopen("trees.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&q);
        memset(head,0,sizeof(head));
        memset(f,0x3f,sizeof(f));
        memset(g,0xcf,sizeof(g));
        tot=0;
        for(int i=1;i<n;++i){
            scanf("%d %d",&u,&v);
            add(u,v);
            add(v,u);
        }
        for(int i=1;i<=n;++i){
            scanf("%d",&score[i]);
        }
        dp(1,0);
        while(q--){
            scanf("%d %d",&xi,&yi);
            if(xi>=f[0][yi]&&xi<=g[0][yi]){
                puts("YES");
            }
            else puts("NO");
        }printf("\n");
    }
    return 0;
}

Note: bzoj need to accelerate to over-read, more time card

Guess you like

Origin www.cnblogs.com/donkey2603089141/p/11414563.html