uva1267Network 树上的最优问题

来源:互联网 发布:java中replacefirst 编辑:程序博客网 时间:2024/05/18 01:37

先将无根树转换为以VOD点为根的有根树,然后从最深的结点开始,每K个祖先放置服务器一次,进行一次DFS,覆盖与他距离不超过K的所有结点,本题只需要覆盖叶子,而不需要覆盖中间结点,而且深度不超过K的叶子已经被原服务器覆盖,所以只需要处理深度大于K的叶节点即可,用node表存放了每层的结点。

/***************** * Author:fisty * Data:2014-12-12 * uva1267 * 树状网络 * ***************/#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;#define MAX_N 1010int n,k,s;int f[MAX_N];vector<int> G[MAX_N];vector<int> node[MAX_N];bool covered[MAX_N];void dfs(int i, int fa, int d){        //把无根树转换为有根树        int len = G[i].size();        if(d > k && len == 1){                //到VOD的服务器不超过K的结点当做不存在                //将与根节点S距离大于k的子叶结点全部分层保存起来                node[d].push_back(i);      //第d层有子叶结点 i                 //printf("d:%d  i:%d\n", d, i);        }        f[i] = fa;        for(int j = 0;j < len;j++){                int v = G[i][j];                if(v != fa){                        dfs(v, i, d+1);                }        }}void dfs2(int u, int fa, int d){        //在节点u放置服务器        covered[u] = true;               //将此节点设为已被覆盖        int len = G[u].size();                   for(int i = 0;i < len; i++){                      int v = G[u][i];                          if(v != fa && d < k)     //只覆盖到新服务器距离不超过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 < node[d].size(); i++){                        int u = node[d][i];                        if(covered[u])  continue; //如果被覆盖跳过                        int v = u;                        for(int j = 0;j < k; j++) v = f[v];    //向上跟新到第k祖先                        dfs2(v, -1, 0);      //在节点V放置服务器                        ans++;                }        }        return ans;}int main(){        int t;        scanf("%d", &t);        while(t--){                scanf("%d%d%d", &n, &s, &k);                for(int i = 0;i <= n; i++){                        G[i].clear();                        node[i].clear();                }                for(int i = 0;i < n-1; i++){                        //树状网络,N-1条边                        int a, b;                        scanf("%d%d", &a, &b);                        G[a].push_back(b);                        G[b].push_back(a);                }                dfs(s, -1, 0);        //传入根节点0,他的父节点设为-1, 0为最高层                printf("%d\n", solve());        }        return 0;}


0 0