d[u][0][1]=sum{d[v][0]}
d[u][1][1]=d[u][1][0]=sum{min(d[v][0],d[v][1])}
d[u][0][0]=sum{d[v][0]}-d[min][0]+d[min][1] (d[min][1]=min(d[v][1]))
调了很久。。。。 看到lrj是先dfs找好路径,再反方向沿着路径递推。O(n)。
最近效率低下!
谁笑到最后谁笑得最好!
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<vector> 5 #define pb push_back 6 using namespace std; 7 const int inf=1e4; 8 const int maxn=10010; 9 int n; 10 vector<int> vt[maxn]; 11 int d[maxn][2][2]; 12 int dp(int u,int p,int f,int fa)//父节点是fa,父节点的决策f,当前结点的决策p,当前结点u 13 { 14 int &ans=d[u][p][f]; 15 if(vt[u].empty()) return 1; 16 if(vt[u].size()==1&&vt[u][0]==fa) return ans=((!p&&!f)?inf:p); 17 if(ans>-1) return ans; 18 ans=p; 19 int mn=inf; 20 for(int i=0;i<vt[u].size();i++) 21 { 22 int v=vt[u][i]; 23 if(v==fa) continue; 24 if(p) 25 { 26 int d1=dp(v,0,p,u); 27 int d2=dp(v,1,p,u); 28 ans+=min(d1,d2); 29 } 30 else if(f) ans+=dp(v,0,p,u); 31 else 32 { 33 ans+=dp(v,0,p,u); 34 mn=min(mn,dp(v,1,p,u)-d[v][0][p]); 35 } 36 } 37 if(!p&&!f) ans+=mn; 38 return ans; 39 } 40 int main() 41 { 42 while(scanf("%d",&n)&&n>-1) 43 { 44 if(n==0) scanf("%d",&n); 45 for(int i=1;i<=n;i++) vt[i].clear(); 46 memset(d,-1,sizeof(d)); 47 for(int i=1;i<=n-1;i++) 48 { 49 int u,v; 50 scanf("%d%d",&u,&v); 51 vt[u].pb(v); 52 vt[v].pb(u); 53 } 54 printf("%d ",min(dp(1,0,0,0),dp(1,1,0,0))); 55 } 56 }