UVA - 1267 Network

题意:n台机器连成一个树状网络,其中叶节点是客户端,其他节点是服务器,目前有一台服务器正在提供服务,你的任务是在一些其他服务器安装使它提供服务,每台客户端到最近服务器的距离不超过K,求安装的最少服务器是多少

思路:将无根树转变为有根树有助于解题,而本题已经有了一个天然的根节点,对于满足条件的节点直接当作不存在就可以了。一般对于一个叶节点u,我们肯定是选择u的k级祖先安装服务器,而每放一次服务器,进行一次DFS,将距离它不超过K的所有节点标记

这道题的最优的地方是:我们可用nodes表避开“按深度排序”的操作

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 1010;

vector<int> gr[MAXN],nodes[MAXN];
int n,s,k,fa[MAXN];
bool covered[MAXN];

void dfs(int u,int f,int d){
    fa[u] = f;
    int nc = gr[u].size();
    if (nc == 1 && d > k)   //只要记录叶子节点
        nodes[d].push_back(u);
    for (int i = 0; i < nc; i++){
        int v = gr[u][i];
        if (v != f)
            dfs(v,u,d+1);
    }
}

void dfs2(int u,int f,int d){
    covered[u] = true;
    int nc = gr[u].size();
    for (int i = 0; i < nc; i++){
        int v = gr[u][i];
        if (v != f && d < k)
            dfs2(v,u,d+1);
    }
}

int solve(){
    int ans = 0;
    memset(covered,0,sizeof(covered));
    for (int d = n-1; d > k; d--)
        for (int i = 0; i < nodes[d].size(); i++){
            int u = nodes[d][i];
            if (covered[u])
                continue;
            int v = u;
            for (int j = 0; j < k; j++)
                v = fa[v];
            dfs2(v,-1,0);
            ans++;
        }
    return ans;
}

int main(){
    int t;
    scanf("%d",&t);
    while (t--){
        scanf("%d%d%d",&n,&s,&k);
        for (int i = 1; i <= n; i++){
            gr[i].clear();
            nodes[i].clear();
        }
        for (int i = 0; i < n-1; i++){
            int a,b;
            scanf("%d%d",&a,&b);
            gr[a].push_back(b);
            gr[b].push_back(a);
        }
        dfs(s,-1,0);
        printf("%d\n",solve());
    }
    return 0;
}



你可能感兴趣的:(UVA - 1267 Network)