Perfect service(树形dp)
Posted PECHPO
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Perfect service(树形dp)相关的知识,希望对你有一定的参考价值。
Perfect service(树形dp)
有n台机器形成树状结构,要求在其中一些机器上安装服务器,使得每台不是服务器的计算机恰好和一台服务器计算机相邻。求服务器的最小数量。n<=10000。
这种类似独立集的树形dp问题,都可以将同一个结点的状态分成几类。这里用\(f[i][0]\)表示i是服务器,\(f[i][1]\)表示i不是服务器,但是i的父亲是服务器。\(f[i][2]\)表示i和i的父亲都不是服务器。
那么就可以写出转移方程:\(f[i][0]=sum(min(f[v][0], f[v][1]))+1\),\(f[i][1]=sum(f[v][2])\),\(f[i][2]=min(f[i][1]-f[v][2]+f[v][0])\)。时间复杂度为\(O(n)\)。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e4+5;
int cntedge, fir[maxn];
struct Edge{
int to, next;
}e[maxn];
void RESET(){ cntedge=0; memset(fir, 0, sizeof(fir)); }
void addedge(int x, int y){
Edge &e1=e[++cntedge];
e1.to=y; e1.next=fir[x]; fir[x]=cntedge;
}
int n, f[maxn][3]; //0:自己是 1:父亲是 2:自己和父亲都不是
//也可以保存访问顺序,在外部访问
void dfs(int u, int par){
f[u][0]=1; f[u][1]=0;
f[u][2]=n; int v;
for (int i=fir[u]; i; i=e[i].next){
if ((v=e[i].to)==par) continue;
dfs(v, u);
f[u][0]+=min(f[v][0], f[v][1]);
f[u][1]+=f[v][2];
}
for (int i=fir[u]; i; i=e[i].next){
if ((v=e[i].to)==par) continue;
f[u][2]=min(f[u][2], f[u][1]-f[v][2]+f[v][0]);
}
}
int main(){
int t1=0, t2;
while (~t1&&~scanf("%d", &n)){
RESET();
for (int i=1; i<n; ++i){
scanf("%d%d", &t1, &t2);
addedge(t1, t2); addedge(t2, t1); }
dfs(1, 0);
printf("%d\n", min(min(f[1][0], f[1][1]), f[1][2]));
scanf("%d", &t1);
}
return 0;
}
以上是关于Perfect service(树形dp)的主要内容,如果未能解决你的问题,请参考以下文章
Perfect Service UVA - 1218(树形dp)
POJ3398Perfect Service[树形DP 树的最大独立集变形]
UVA-1220-Party at Hali-Bula && UVA-1218-Perfect Service(树形DP)