很久之前做的题,今天又做到了,顺手来补一下题解。。。
题意:有n台电脑,互相以无根树的方式连接。现在将其中一些电脑作为服务器,且要求每台电脑有且必须连接一台服务器。(不包括本身是服务器的电脑),问需要多少台电脑作为服务器。
思路:
设u是父亲,v是u的孩子。
d(u,0):u本身是服务器;
d(u,1):u不是服务器,u的父亲是服务器。
d(u,2):u不是服务器,u的父亲不是服务器,u的孩子必须有且只有一个是服务器。
那么就能得出
d(u,0) = Sum(d(v,1));
d(u,1) = Sum(d(v,2));
d(u,2) = min(d(u,2), d(u,1)-d(v,2)+d(v,0));
代码:注意d[u][2]不要初始化inf,这样累加的时候会超上限,因为这个wa了好多次。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 10010;
int n;
vector<int>g[maxn];
int dp[maxn][3];
int vis[maxn];
void dfs(int u)
{
queue<int>q;
vis[u] = 1;
dp[u][0] = 1;
dp[u][1] = 0;
dp[u][2] = n;
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(!vis[v])
{
dfs(v);
q.push(v);
dp[u][0] += min(dp[v][0],dp[v][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();
}
}
int main()
{
while(cin>>n)
{
if(n==0)
continue;
if(n==-1)
break;
for(int i = 1; i <= n; i++)
g[i].clear();
for(int i = 0; i < n-1; i++)
{
int u,v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
memset(vis,0,sizeof(vis));
dfs(1);
int ans = min(dp[1][0],dp[1][2]);
cout<<ans<<endl;
}
return 0;
}