Perfect Service UVA
来源:互联网 发布:php特殊字符转义函数 编辑:程序博客网 时间:2024/06/08 05:27
树形DP
题目描述:求最少的服务器,使得其他不是服务器的计算机恰好和一台服务器计算机相邻。
解题分析:定义dp[u][0] u是服务器,每个子节点可以使服务器也可以不是。
dp[u][0] = sum(min(dp[v][0],dp[v][1])).
dp[u][1] u不是服务器,但u的父亲是服务器,所以u的所有子节点都不是服务器。
dp[u][1] = sum(dp[v][2]).
dp[u][2],u和u的父亲都不是服务器,所以u的儿子中必须恰好有一个儿子是服务器。
dp[u][2] = min(dp[v][0] + sum(others dp[v][2])).如果遍历每一个结点作为选定的服务器儿子,那么时间复杂度将会是k^2,k是子节点的个数。但实际上可以不用这样重复计算,
因为sum(dp[v][2])已经在dp[u][1]里面给计算过了,所以可以利用上面的结果。则
dp[u][2] = min(dp[u][1] - dp[v][1] + dp[v][0]).
第一遍写的代码:
有两点不太明白,一直WA,第一个是在边界处理上,如果u没有子节点的话,dp[u][2] = maxn, 而我之前写的是dp[u][2] = 0;
第二点不明白的是:为什么dp[u][2]的初始化为0x3f3f3f3f就会WA呢,感觉没什么问题啊,哦,明白了,如果初始化为0x3f3f3f3f的话,n个0x3f3f3f3f相加就会数据溢出了。
代码如下:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>using namespace std;const int maxn = 10000 + 10;const int INF = 0x3f3f3f3f;int par[maxn];vector<int> temp[maxn];vector<int> son[maxn];int dp[maxn][3];int n;int dfs(int u){ if(son[u].size() == 0) { dp[u][0] = 1; dp[u][1] = 0; dp[u][2] = maxn; } else { for(int i = 0; i < son[u].size(); i++) { dfs(son[u][i]); } int sum0 = 0,sum1 = 0; for(int i = 0; i < son[u].size(); i++) { int v = son[u][i]; sum0 += min(dp[v][1],dp[v][0]); sum1 += dp[v][2]; } dp[u][0] = sum0 + 1; dp[u][1] = sum1; for(int i = 0; i < son[u].size(); i++) { int v = son[u][i]; dp[u][2] = min(dp[u][2],dp[u][1]-dp[v][2] + dp[v][0]); } }}void build_tree(int u,int p){ for(int i = 0;i < temp[u].size(); i++) { int v = temp[u][i]; if(v != p) { par[v] = u; build_tree(v,u); } }}int main(){ while(cin >> n && n!= -1) { if(n == 0) continue; for(int i = 0; i <= n; i++) { son[i].clear(); temp[i].clear(); par[i] = i; dp[i][2] = maxn; } int x,y; for(int i = 0; i < n-1; i++) { cin >> x >> y; temp[y].push_back(x); temp[x].push_back(y); } int root = 1; par[root] = 0; build_tree(root,0); for(int i = 1; i <= n; i++) { son[par[i]].push_back(i); } dfs(1); printf("%d\n",min(dp[root][0],dp[root][2])); } return 0;}
后来发觉有大佬直接对无根树处理,只需要递归的时候判断一下是不是父节点就行
代码如下:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <vector>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 10000 + 10;vector <int> graph[maxn];int dp[maxn][3];int n;void dfs(int u,int fa){ dp[u][0] = 1; dp[u][1] = 0; dp[u][2] = maxn; for(int i = 0; i < graph[u].size(); i++) { int v = graph[u][i]; if(v != fa) { dfs(v,u); } } for(int i = 0; i < graph[u].size(); i++) { int v = graph[u][i]; if(v == fa) continue; dp[u][0] += min(dp[v][0],dp[v][1]); dp[u][1] += dp[v][2]; } for(int i = 0; i < graph[u].size(); i++) { int v = graph[u][i]; if(v == fa) continue; dp[u][2] = min(dp[u][2],dp[u][1] - dp[v][2] + dp[v][0]); }}int main(){ while(cin >> n && n != -1) { if(n == 0) continue; for(int i = 0; i <= n; i++) { dp[i][2] = maxn; graph[i].clear(); } for(int i = 0; i < n-1; i++) { int x,y; scanf("%d %d",&x,&y); graph[x].push_back(y); graph[y].push_back(x); } dfs(1,0); printf("%d\n",min(dp[1][0],dp[1][2])); } return 0;}
阅读全文
0 0
- UVA 1218Perfect Service
- UVa 1218 Perfect Service
- Uva-1218 Perfect Service
- UVA-1218 Perfect Service
- UVa-1228 Perfect Service
- UVA 1218 Perfect Service
- Perfect Service UVA
- Perfect Service UVA
- Perfect Service - UVa 1218 dp
- 【UVA】1218 - Perfect Service(动态规划)
- UVa #1218 Perfect Service (例题9-14)
- UVa 1218 Perfect Service [DFS+DP]
- UVa 1218 - Perfect Service(树形DP)
- UVa 1218:Perfect Service(DP)
- uva 1218 Perfect Service 树形dp
- uva 1218——Perfect Service
- UVA - 1218 Perfect Service(树形dp)
- UVA 1218 Perfect Service [树形dp]
- Python中下划线
- Scala学习之构造器
- Linux基础
- EventBus的Sticky粘性事件
- Rxjava前哨——观察者设计模式
- Perfect Service UVA
- linux基本命令
- ansible(一)简单的东西应该简单,复杂的才能成功
- SpringMVC自定义拦截器与异常处理
- 笔试笔记(七)
- ubuntu安装必要的软件
- settings.db应用 笔记:
- 使用wireshark抓取视频流中的H264协议,并分析
- HDU6146 Pokémon GO (2017百度之星程序设计大赛