Perfect service(樹形dp)
阿新 • • 發佈:2018-04-17
sin space cst ice return 服務器 scan con 表示 。時間復雜度為\(O(n)\)。
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])\)
#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)