bzoj5072(樹形揹包DP)
阿新 • • 發佈:2018-12-09
樹DP可以維護有沒有黑點數為y的聯通塊,但不能保證點數,所以多一維肯定是炸了。。
然而有個顯然的結論是,如果點數為x的黑點數最小為min,最大為max,那麼[min,max]這個區間的黑點數一定存在
所以只需要維護點數為x的最小黑點和最大黑點就可以了。。
然後樹揹包dp隨便轉移,複雜度O(n^2)
/** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ┃ * ┃ > < ┃ * ┃ ┃ * ┃... ⌒ ... ┃ * ┃ ┃ * ┗━┓ ┏━┛ * ┃ ┃ Code is far away from bug with the animal protecting * ┃ ┃ 神獸保佑,程式碼無bug * ┃ ┃ * ┃ ┃ * ┃ ┃ * ┃ ┃ * ┃ ┗━━━┓ * ┃ ┣┓ * ┃ ┏┛ * ┗┓┓┏━┳┓┏┛ * ┃┫┫ ┃┫┫ * ┗┻┛ ┗┻┛ */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,l,r) for(int i=l;i>=r;i--) #define link(x) for(edge *j=h[x];j;j=j->next) #define mem(a) memset(a,0,sizeof(a)) #define ll long long #define eps 1e-12 #define succ(x) (1<<x) #define lowbit(x) (x&(-x)) #define sqr(x) ((x)*(x)) #define mid (x+y>>1) #define NM 5005 #define nm 10005 #define pi 3.1415926535897931 const ll inf=1e9; using namespace std; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } struct edge{int t;edge*next;}e[nm],*h[NM],*o=e; void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} int n,m,_x,_y,d[NM][NM],g[NM][NM],a[NM],f[NM],size[NM]; void dfs(int x){ d[x][1]=g[x][1]=a[x]==1; size[x]=1; inc(i,2,n)g[x][i]=inf; link(x)if(f[x]!=j->t){ f[j->t]=x; dfs(j->t); size[x]+=size[j->t]; dec(v,size[x],2)inc(k,max(1,v+size[j->t]-size[x]),min(size[j->t],v-1)) d[x][v]=max(d[x][v],d[x][v-k]+d[j->t][k]), g[x][v]=min(g[x][v],g[x][v-k]+g[j->t][k]); } } int main(){ int _=read();while(_--){ mem(e);mem(h);o=e;mem(d); n=read();m=read(); inc(i,2,n){_x=read();_y=read();add(_x,_y);add(_y,_x);} inc(i,1,n)a[i]=read(); dfs(1); inc(i,2,n)inc(j,1,size[i])d[1][j]=max(d[1][j],d[i][j]),g[1][j]=min(g[1][j],g[i][j]); while(m--){ _x=read();_y=read(); puts(g[1][_x]<=_y&&_y<=d[1][_x]?"YES":"NO"); } printf("\n"); } return 0; }
5072: [Lydsy1710月賽]小A的樹
題目描述
給出一棵n個點的樹,每個點有黑白兩種顏色。q次詢問,每次詢問給出x和y,問能否選出一個x個點的聯通子圖,使得其中黑點數目為y。
輸入
第一行一個正整數 T 表示資料組數。 對於每一組資料,第一行有兩個用空格隔開的正整數,分別是 n 和 q ,表示樹的節點數和詢問次數。 接下來 n-1 行,每行兩個用空格隔開的正整數和,表示和間有一條邊相連。 接下來一行有 n 個用空格隔開的整數,其中若,則表示第 i 個點為白色,否則為黑色。 接下來 q 行,每行兩個用空格隔開的整數 x 和 y 。 n<=5000,q<=10^5
輸出
對於每一組資料,輸出 q 行,每行為 “YES” 或者 “NO” (不含雙引號),表示對於給定的和,能否滿足小A 的要求。 每相鄰兩組資料的輸出之間空一行。
樣例輸入
1 9 4 4 1 1 5 1 2 3 2 3 6 6 7 6 8 9 6 0 1 0 1 0 0 1 0 1 3 2 7 3 4 0 9 5
輸出
YES YES NO NO