【BZOJ3935】Rbtree 樹形DP
阿新 • • 發佈:2017-11-26
ron size [1] 挖礦 brush val nbsp 結點 它的
輸出一個數表示答案;如果無解,輸出 “-1”。
1 0 0
1 2 2
2 3 2
【BZOJ3935】Rbtree
Description
給定一顆 N 個點的樹,樹上的每個點或者是紅色,或者是黑色。 每個單位時間內,你可以任選兩個點,交換它們的顏色。 出於某種惡趣味,你希望用最少的時間調整結點的顏色,使得對於每個點,離它最近的黑色點與它的距離不超過 x。Input
輸入的第一行包含整數 N 和 x(1 <= x <= 10^9)。 接下來一行 N 個整數 C1-Cn,表示結點的初始顏色。1 表示黑色,0 表示紅色。 接下來 N-1 行,每行 3 個整數 ui, vi,wi(1 <= wi <= 10^9),表示點 ui 和 vi 之間存在權值為 wi的邊。Output
Sample Input
3 21 0 0
1 2 2
2 3 2
Sample Output
1HINT
數據規模和約定 對於100%的數據 N<=500題解:大神們寫的都是單純形?算了我只知道樹形DP。
本題的思路和小奇挖礦相同。用f[x][a][b]表示在x的子樹中放a個黑點,且距離x最近的黑點是b的最小花費(即有多少點從白點變成黑點)。轉移時,對於a那維相當於樹形背包,我們考慮b那維怎麽轉移。
如果我們想用f[y][..][c]來更新f[x][..][b],那麽討論:如果b==c,直接轉移即可;如果c在y的子樹中,那麽用f[y][..][c]的最大值來更新f[x][..][b]即可;如果c不在y的子樹中,那麽我們將b換成c或者將c換成b一定不會變的更差,所以:不用轉移!
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; int n,m,ans,cnt; ll K; int v[505],p[505],q[505],Q[505],siz[505],g[505][505],to[1010],next[1010],head[505]; int f[505][505][505]; ll dis[505][505],val[1010]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } inline void add(int a,int b,int c) { to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++; } void dfs1(int x,int fa,int y) { if(y==1) p[x]=++p[0],Q[p[0]]=x; for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) dis[to[i]][y]=dis[x][y]+val[i],dfs1(to[i],x,y); if(y==1) q[x]=p[0]; } void dfs2(int x,int fa) { int i,y,j,k,a,mn; siz[x]=1; for(a=1;a<=n;a++) if(a!=x&&dis[a][x]<=K) f[x][0][a]=0; f[x][1][x]=!v[x]; for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) { y=to[i],dfs2(y,x); memset(g,0x3f,sizeof(g)); for(j=0;j<=siz[x]&&j<=m;j++) for(k=0;k<=siz[y]&&j+k<=m;k++) { mn=0x3f3f3f3f; for(a=p[y];a<=q[y];a++) mn=min(mn,f[y][k][Q[a]]); for(a=1;a<=n;a++) g[j+k][a]=min(g[j+k][a],f[x][j][a]+f[y][k][a]); for(a=1;a<p[y];a++) g[j+k][Q[a]]=min(g[j+k][Q[a]],f[x][j][Q[a]]+mn); for(a=q[y]+1;a<=n;a++) g[j+k][Q[a]]=min(g[j+k][Q[a]],f[x][j][Q[a]]+mn); } siz[x]+=siz[y]; for(j=0;j<=siz[x]&&j<=m;j++) for(a=1;a<=n;a++) f[x][j][a]=g[j][a]; } } int main() { n=rd(),K=rd(); int i,a,b,c; memset(head,-1,sizeof(head)); for(i=1;i<=n;i++) v[i]=rd(),m+=v[i]; for(i=1;i<n;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c); for(i=1;i<=n;i++) dfs1(i,0,i); memset(f,0x3f,sizeof(f)); dfs2(1,0); ans=1<<30; for(i=1;i<=n;i++) ans=min(ans,f[1][m][i]); printf("%d",ans>n?-1:ans); return 0; }
【BZOJ3935】Rbtree 樹形DP