UVA - 1218 Perfect Service(树形dp)
题目链接: id=36043">UVA - 1218 Perfect Service
题意
有n台电脑。互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连接且仅仅能连接一台server(不包含作为server的电脑)。求最少须要多少台电脑作为server。
思路
典型的树形dp问题,那么我们来建立模型。
d(u,0):u是server,孩子是不是server均可
d(u,1):u不是server,u的父亲是server,u的孩子不能是server
d(u,2):u不是server且u的父亲不是server,u的孩子必须有且仅有一个是server。那么显然的
d(u,0) = 1 + Sum( Min(d(v,1), d(v,0)) ) |v是u的孩子
d(u,1) = Sum(d(v,2))
d(u,2)稍复杂些。由于仅仅能有一个孩子是server,所以须要遍历每一个孩子为server的情况,每一轮遍历都要同一时候计算其它全部孩子,须要O(N^2)的时间。
显然这样会有非常多反复计算的情况,当然能够记忆化来加高速度,可是另一个更快的小技巧。由于d(u,1)和d(u,2)的唯一差别就是d(u,2)的孩子有一个server
那么我们能够得出
d(u,2) = Min(d(u,1)-d(v,2)+d(v,0)) |v是u的孩子
仍是遍历设每一个孩子为server。每一轮的操作为O(1),整体为O(N)
代码
ps:由于d(u,2)初始要设为无穷大,就设了0x3f3f3f3f,结果改成N就好了,找了好久才找出问题出在这,由于这个wrong了好多遍,但还是不知道为什么会wrong,知道原因的道友请不吝指点。
第一遍a的代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
const int N = 10009;
vector<int> g[N];
int dp[N][3];
void dfs(int u, int fa)
{
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
dfs(g[u][i], u);
}
dp[u][0] = 1;
dp[u][1] = 0;
dp[u][2] = N;
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
{
dp[u][0] += min(dp[g[u][i]][0], dp[g[u][i]][1]);
dp[u][1] += dp[g[u][i]][2];
}
}
bool f = true;
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
{
f = false;
dp[u][2] = min(dp[u][2], dp[u][1]+dp[g[u][i]][0]-dp[g[u][i]][2]);
}
}
}
int main()
{
int n;
while(cin>>n)
{
memset(dp, -1, sizeof(dp));
int a, b;
for(int i=1; i<n; i++)
{
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, -1);
cout<<min(dp[1][0], dp[1][2])<<endl;
cin>>a;
if(a == -1)
break;
for(int i=1; i<=n; i++)
g[i].clear();
}
return 0;
}
观摩大神代码后进行改动的精简版
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
const int N = 10009;
vector<int> g[N];
int dp[N][3];
void dfs(int u, int fa)
{
dp[u][0] = 1;
dp[u][1] = 0;
dp[u][2] = N;
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
{
dfs(g[u][i], u);
dp[u][0] += min(dp[g[u][i]][0], dp[g[u][i]][1]);
dp[u][1] += dp[g[u][i]][2];
}
}
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i] != fa)
dp[u][2] = min(dp[u][2], dp[u][1]+dp[g[u][i]][0]-dp[g[u][i]][2]);
}
}
int main()
{
int n;
while(cin>>n)
{
int a, b;
for(int i=1; i<n; i++)
{
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, -1);
cout<<min(dp[1][0], dp[1][2])<<endl;
cin>>a;
if(a == -1)
break;
for(int i=1; i<=n; i++)
g[i].clear();
}
return 0;
}
UVA - 1218 Perfect Service(树形dp)的更多相关文章
- UVA - 1218 Perfect Service (树形dp)(inf相加溢出)
题目链接 题意:给你一个树形图,让你把其中若干个结点染成黑色,其余的染成白色,使得任意一个白色结点都恰好与一个黑色结点相邻. 解法比较容易,和树上的最大独立集类似,取一个结点作为树根,对每个结点分三种 ...
- UVa 1218 - Perfect Service
/*---UVa 1218 - Perfect Service ---首先对状态进行划分: ---dp[u][0]:u是服务器,则u的子节点可以是也可以不是服务器 ---dp[u][1]:u不是服务器 ...
- UVA - 1218 Perfect Service (树形DP)
思路:dp[i][0]表示i是服务器:dp[i][1]表示i不是服务器,但它的父节点是服务器:dp[i][2]表示i和他的父亲都不是服务器. 转移方程: d[u][0] += min(d[ ...
- UVa 1218 - Perfect Service(树形DP)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVa 1218 Perfect Service 完美的服务
***状态设计值得一看dp[u][0]表示u是服务器(以下v均指任意u的子结点,son指u的所有子结点)ap[u][0]=sum{dp[v][1]}+1//错误,服务器是可以和其他服务器相邻的dp[u ...
- POJ3398Perfect Service[树形DP 树的最大独立集变形]
Perfect Service Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 1518 Accepted: 733 De ...
- UVa 10859 - Placing Lampposts 树形DP 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- UVa 1292 - Strategic game (树形dp)
本文出自 http://blog.csdn.net/shuangde800 题目链接: 点击打开链接 题目大意 给定一棵树,选择尽量少的节点,使得每个没有选中的结点至少和一个已选结点相邻. 思路 ...
- Uva LA 3902 - Network 树形DP 难度: 0
题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...
随机推荐
- 2013年,移动App设计的13大精髓
摘要:在 过去的一年里,移动成主流也让众多的移动应用如雨后春笋般层出不穷,在众多开发者从中获利的同时竞争也愈演愈烈,如何才能保证自己立于不败之地?用户是上 帝,一切还得从应用说起.本文总结了新一年里A ...
- vim/vi的文件内、跨文件复制粘贴操作、替换操作
vi/vim 中可以使用 :s 命令来替换字符串 1.s/vivian/sky/ 替换当前行第一个 vivian 为 sky 2.:s/vivian/sky/g 替换当前行所有 vivian 为 sk ...
- uva 10994 - Simple Addition(规律)
题目链接:uva 10994 - Simple Addition 题目大意:给出l和r,求∑(l≤i≤r)F(i), F(i)函数题目中有. 解题思路:由两边向中间缩进,然后l和r之间的数可以按照1~ ...
- go语言基础之有参有返回值函数的使用
1.有参有返回值函数的使用 示例1: package main //必须 import "fmt" //go官方推荐写法 func MaxAndMin(a, b int) (max ...
- C#中this的作用
一.C# this指针的几种用法 1.限定被相似的名称隐藏的成员 C# 代码 复制 public class ThisName { public string name = "张三& ...
- ECharts学习总结(一):ECharts的第一个图表
在进行echarts图表开发之前先要到echarts官网下载echarts的库文件,我下载的是echarts-2.2.7.然后把库文件放到工程文件web目录下.接下来进行第一个图表的显示步骤如下: 1 ...
- Java保存简单偏好的类
该类利用Preferences保存文本,数字等简单数据,在Windows平台下,它就保存到了系统注册表中,而Linux中它存在于用户目录下的一个隐藏文件中. public class Pref{ ...
- (LeetCode 72)Edit Distance
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2 ...
- angularjs中的数据绑定
这是一个最简单的angularjs的例子,关于数据绑定的,大家可以执行一下,看看效果 <html ng-app> <head> <title>angularjs-i ...
- Android工程内嵌Flutter
本文记录一下Android主工程中嵌入部分Fluttter页面的实现方法. 创建一个Android工程模拟你的现有工程 为了让Android工程和Flutter工程互不干扰,这里不再以Android工 ...