码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】UVA1218 Perfect Service

时间:2018-08-07 22:54:04      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:strong   efi   space   \n   clu   结束   初始   就是   查找   

UVA1218:https://www.luogu.org/problemnew/show/UVA1218
刷紫书DP题ing

思路

参考lrj紫书 不喜勿喷

  1. d(u,0):u是服务器,孩子是不是服务器均可
  2. d(u,1):u不是服务器,u的父亲是服务器,u的孩子不能是服务器
  3. d(u,2):u不是服务器且u的父亲不是服务器,u的孩子必须有且仅有一个是服务器。

前两个状态方程好写
那么d(u,2)呢?
d(u,2)就会等于 他儿子全都不是 减去某个不是 再加上某个是 这是这道树形DP的难点

因此 状态方程:d(u,2) = Min(d(u,1)-d(v,2)+d(v,0)) |v是u的孩子

详细解释见代码~

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
#define maxn 10010
vector<int> sons[maxn];
int dp[maxn][3];
int n;
void search(int u,int father)
{
   dp[u][0]=1;//本身算一个 
   dp[u][1]=0;
   dp[u][2]=maxn;//要查找 先定义成最大 
   for(int i=0;i<sons[u].size();i++)
   {
       if(sons[u][i]!=father)//如果不是父亲 就是儿子 
       {
           search(sons[u][i],u);//递归查找 
           dp[u][0]+=min(dp[sons[u][i]][0],dp[sons[u][i]][1]);//如果他是 儿子可以是或者不是 
           dp[u][1]+=dp[sons[u][i]][2];//如果他不是 但他父亲是 儿子都不是 
       }
   }
   for(int i=0;i<sons[u].size();i++)
   {
       if(sons[u][i]!=father)
       dp[u][2]=min(dp[u][1]-dp[sons[u][i]][2]+dp[sons[u][i]][0],dp[u][2]);
       //如果他不是 他父亲也不是 那么就是他儿子全都不是减去某个不是再加上某个是 
   }
}
int main()
{
   while(scanf("%d",&n)==1)
   {
       int x,y;
       for(int i=1;i<n;i++)
       {
           scanf("%d%d",&x,&y);//存边 
           sons[x].push_back(y);
           sons[y].push_back(x);
       }
       search(1,-1);
       printf("%d\n",min(dp[1][0],dp[1][2]));//答案在第一个是服务器
                                             //或者第一个不是但是儿子之一是 
       scanf("%d",&x);//数据结束 
       if(x==-1)
       break;
       for(int i=1;i<=n;i++)//初始化 
       sons[i].clear();
       memset(dp,0,sizeof(dp));
   }
}

【题解】UVA1218 Perfect Service

标签:strong   efi   space   \n   clu   结束   初始   就是   查找   

原文地址:https://www.cnblogs.com/BrokenString/p/9439934.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!