1. 程式人生 > >【luogu2458】 [SDOI2006]保安站崗 [動態規劃 樹形dp]

【luogu2458】 [SDOI2006]保安站崗 [動態規劃 樹形dp]

cow gist head algorithm ++ fine txt tps n)

P2458 [SDOI2006]保安站崗

最終決定重新打一遍這題 然後被兒子覆蓋的這個情況還是重新看一遍以前的代碼才捋清楚QAQ

每個點有三種狀態 自己覆蓋自己 被父親覆蓋 被兒子覆蓋

然後要註意被兒子覆蓋時的轉移 最後如果都是兒子被孫子覆蓋的花費更少的話 得選一個兒子自己覆蓋自己花費最少的來覆蓋

最後輸出根節點中自己覆蓋自己和被兒子覆蓋中較小的一個

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<cmath>
 6
#include<stack> 7 #include<algorithm> 8 using namespace std; 9 #define ll long long 10 #define rg register 11 const int N=1500+5,inf=0x3f3f3f3f; 12 int n,a[N],ns,s,f[N][3]; 13 template <class t>void rd(t &x) 14 { 15 x=0;int w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch==
-,ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 x=w?-x:x; 19 } 20 21 int head[N],tot=0; 22 struct edge{int v,nxt,w;}e[N<<1]; 23 void add(int u,int v) 24 { 25 e[++tot].v=v,e[tot].nxt=head[u],head[u]=tot; 26 } 27 28 void dp(int u,int
fa) 29 { 30 f[u][0]=a[u],f[u][1]=f[u][2]=0; 31 bool yes=0;int minc=inf; 32 for(int i=head[u];i;i=e[i].nxt) 33 { 34 int v=e[i].v; 35 if(v==fa) continue; 36 dp(v,u); 37 f[u][0]+=min(f[v][1],min(f[v][0],f[v][2]));//自己覆蓋自己 38 f[u][1]+=min(f[v][0],f[v][2]);//被父親覆蓋 39 f[u][2]+=min(f[v][0],f[v][2]) ;//被兒子覆蓋 40 if(f[v][0]<=f[v][2]) yes=1; 41 else minc=min(minc,f[v][0]-f[v][2]); 42 } 43 if(!yes) f[u][2]+=minc; 44 } 45 46 int main() 47 { 48 //freopen("in.txt","r",stdin); 49 //freopen("nocows.out","w",stdout); 50 rd(n); 51 for(rg int i=1;i<=n;++i) 52 { 53 rd(i),rd(a[i]),rd(ns); 54 for(rg int j=1;j<=ns;++j) rd(s),add(i,s),add(s,i); 55 } 56 dp(1,0); 57 printf("%d",min(f[1][0],f[1][2])); 58 return 0; 59 }

【luogu2458】 [SDOI2006]保安站崗 [動態規劃 樹形dp]