其他分享
首页 > 其他分享> > POJ3398 Perfect Service (树形DP)

POJ3398 Perfect Service (树形DP)

作者:互联网

对于每个u要设置三维。

dp[u][0]表示u是服务器,以u为根的最小服务器数,其子节点既可以是,也可以不是,dp[u][0]+=min(d[v][0],d[v][1]);

dp[u][1]表示u不是服务器,但他的父节点时,此时u的子节点都不可能是,dp[u][1]+=dp[v][2];

dp[u][2]表示u及其父亲都不是服务器,u的子节点只有一个是服务器,枚举这个子节点,dp[u][2]=min(d[u][2],d[v1][2]+d[v2][2]+...+d[v][0]),但是我们这样枚举的话,复杂度是O(k2),我们发现求解dp[u][1]时已经求到了dp[v][2]的总和,那么我们可以借用这个优化到O(k):d[u][2]=min(d[u][2],d[u][1]-d[v][2]+d[v][0]).

最后的求解目标就是min(dp[1][0],dp[1][2]). (将1看成树根)

 1 #include<cstdio> 
 2 #include<cstring>
 3 #include<vector>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=10000+5;
 7 int n;
 8 vector<int> E[maxn];
 9 int dp[maxn][3];
10 
11 void dfs(int u,int fa){
12     dp[u][0]=1;//自身是服务器 
13     dp[u][1]=0;//自身不是,父亲是
14     dp[u][2]=maxn;//自己和父亲都不是 
15     int k=E[u].size();
16     if(k==1&&fa!=0) return ;
17     for(int i=0;i<k;i++){
18         int v=E[u][i];
19         if(v==fa) continue;
20         dfs(v,u);
21         dp[u][0]+=min(dp[v][0],dp[v][1]);
22         dp[u][1]+=dp[v][2];
23     }
24     for(int i=0;i<k;i++){
25         int v=E[u][i];
26         if(v==fa) continue;
27         dp[u][2]=min(dp[u][2],dp[u][1]-dp[v][2]+dp[v][0]);
28     }
29 }
30 
31 int main(){
32     int u,v;
33     while(~scanf("%d",&n)){
34         for(int i=1;i<=n;i++) E[i].clear();
35         for(int i=1;i<n;i++){
36             scanf("%d%d",&u,&v);
37             E[u].push_back(v);
38             E[v].push_back(u);//正反向边都要建 
39         }
40         dfs(1,0);//哪个节点作为树根并不影响 
41         printf("%d\n",min(dp[1][0],dp[1][2]));
42         scanf("%d",&u);
43         if(u==-1) break;
44     }
45     return 0;
46 }

 

标签:Perfect,POJ3398,min,int,maxn,DP,服务器,include,dp
来源: https://www.cnblogs.com/yhxnoerror/p/16387892.html