UVa-1218

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 }
原文地址:https://www.cnblogs.com/windrises/p/4818102.html