uva1218树形dp
题意:有n台机器形成树形结构。要求在其中一些机器上安装服务器,使得每台不是服务器的计算机恰好和一台服务器计算机相邻。求服务器最少的数量。
思路:所有机器分为3种:
dp[u][0]:是服务器,故该节点的孩子任意。dp[u][0]=sum{min(dp[v][0],dp[v][1])}
dp[u][1]:不是服务器,但父亲是服务器,故该节点的孩子不能有服务器。dp[u][1]=sum{dp[v][2]}
dp[u][2]:不是服务器且其父亲也不是服务器,故给节点的恰好有一个孩子是服务器。遍历复杂度高,可用之前所算出的结果计算:d[u][2]=min(d[u][1]-d[v][2]+d[v][0])
最后输出min(d[1][0],d[1][2]),因为作为根节点的1没有父亲,所以他的子节点不能没有服务器。所以没有dp[1][1]的情况。
树形结构,但在输入联系的时候没有规定父亲和儿子,所以作为图来搜没有被访问过的点。
队列用来记录每个节点的孩子。
dfs
#include<bits/stdc++.h> using namespace std; int dp[10000+10][3]; vector<int>line[10000+10]; int vis[10000+10]; void dfs(int u) { vis[u]=1; dp[u][0]=1;dp[u][1]=0;dp[u][2]=10000+10; queue<int>q; for(int i=0;i<line[u].size();i++) { int v=line[u][i]; if(!vis[v]) { dfs(v); q.push(v); dp[u][0]=dp[u][0]+min(dp[v][0],dp[v][1]); dp[u][1]=dp[u][1]+dp[v][2]; } } while(!q.empty()){ dp[u][2]=min(dp[u][2],dp[u][1]-dp[q.front()][2]+dp[q.front()][0]); q.pop(); } return; } int main() { while(1) { int n; cin>>n; if(!n)continue; if(n==-1)break; memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++)line[i].clear(); for(int i=0;i<n-1;i++) { int a,b; cin>>a>>b; line[a].push_back(b); line[b].push_back(a); } dfs(1); cout<<min(dp[1][0],dp[1][2])<<endl; } return 0; }