UVA LA3902-network(树形dp)

来源:互联网 发布:淘宝店铺英文名字 编辑:程序博客网 时间:2024/06/03 23:17

Consider a tree network with n nodes where the internal nodes correspond to servers and the terminal nodes correspond to clients. The nodes are numbered from 1 to n . Among the servers, there is an original server Swhich provides VOD (Video On Demand) service. To ensure the quality of service for the clients, the distance from each client to the VOD server S should not exceed a certain value k . The distance from a node u to a node v in the tree is defined to be the number of edges on the path from u to v . If there is a nonempty subset C of clients such that the distance from each u in C to S is greater than k , then replicas of the VOD system have to be placed in some servers so that the distance from each client to the nearest VOD server (the original VOD system or its replica) is k or less.

Given a tree network, a server S which has VOD system, and a positive integer k , find the minimum number of replicas necessary so that each client is within distance k from the nearest server which has the original VOD system or its replica.

For example, consider the following tree network.

\epsfbox{p3902.eps}

In the above tree, the set of clients is {1, 6, 7, 8, 9, 10, 11, 13}, the set of servers is {2, 3, 4, 5, 12, 14}, and the original VOD server is located at node 12.

For k = 2 , the quality of service is not guaranteed with one VOD server at node 12 because the clients in {6, 7, 8, 9, 10} are away from VOD server at distance > k . Therefore, we need one or more replicas. When one replica is placed at node 4, the distance from each client to the nearest server of {12, 4} is less than or equal to 2. The minimum number of the needed replicas is one for this example.

Input 

Your program is to read the input from standard input. The input consists of T test cases. The number of test cases (T ) is given in the first line of the input. The first line of each test case contains an integer n (3$ \le$n$ \le$1, 000) which is the number of nodes of the tree network. The next line contains two integers s (1$ \le$s$ \le$n) and k (k$ \ge$1) where s is the VOD server and k is the distance value for ensuring the quality of service. In the following n - 1 lines, each line contains a pair of nodes which represent an edge of the tree network.

Output 

Your program is to write to standard output. Print exactly one line for each test case. The line should contain an integer that is the minimum number of the needed replicas.

Sample Input 

2 14 12 2 1 2 2 3 3 4 4 5 5 6 7 5 8 5 4 9 10 3 2 12 12 14 13 14 14 11 14 3 4 1 2 2 3 3 4 4 5 5 6 7 5 8 5 4 9 10 3 2 12 12 14 13 14 14 11

Sample Output 

1 0

 

 

题意大概是说n个机器连接成一个树状网络,叶子结点是客户端,其他结点是主服务器,距离为k以内的叶节点网络正常,但是距离大于k的范围的叶节点会出现网络延迟,为了使所有结点都覆盖到信号,问怎样放置使得所有节点都能覆盖到且用的服务器数目最少?

 

分析:把这个问题抽象成一个无向图不难发现,距离主服务器距离不超过k的叶节点均会被覆盖到,我们关心的是距离主服务器大于k的那些结点,对于这些节点该如何处理呢?

不难发现,在其k级祖先处放置服务器无疑是最优解。因为此时该节点(u)即距离其k级祖先的叶节点均会被覆盖到。那么预处理出所有深度大于k的叶节点(需要一遍dfs)插入到nodes表之后,在dfs一遍,把这些结点覆盖完即可,最后累加需要的服务器数即为最终答案。

代码如下:(附加注释)

 

/***************************** author:crazy_石头* date:2014/01/13* algorithm:dfs* Pro:LA 3902-network*****************************/#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>#include <vector>using namespace std;#define INF 1<<29#define eps 1e-8#define A system("pause")#define rep(i,h,n) for(int i=(h);i<(n);i++)#define ms(a,b) memset((a),(b),sizeof(a))const int maxn=1000+10;vector<int>g[maxn],nodes[maxn];//按深度把叶子节点存进来;int n,s,k,fa[maxn];//方便找k级祖先;bool covered[maxn];inline void dfs(int u,int f,int d)//分别表示当前结点,父节点及深度d;函数是将叶节点插入到nodes表中;{    fa[u]=f;    int c=g[u].size();    if(c==1&&d>k) nodes[d].push_back(u);//是叶节点并且所在结点不能被主服务器覆盖到,那么插入到nodes表中;    rep(i,0,c)    {        int v=g[u][i];        if(v==f) continue;        dfs(v,u,d+1);    }}inline void dfs1(int u,int f,int d){    covered[u]=true;//覆盖了当前结点;    int c=g[u].size();    rep(i,0,c)    {        int v=g[u][i];        if(v!=f&&d<k)//距离能在主服务器覆盖范围内的话就覆盖掉它;            dfs1(v,u,d+1);    }}inline int solve(){    int ret=0;    ms(covered,0);//初始时均未覆盖;    for(int d=n-1;d>k;d--)//枚举不同的深度;    rep(i,0,nodes[d].size())    {        int u=nodes[d][i];        if(covered[u]) continue;//若已经覆盖掉,就跳过;        int v=u;        rep(i,0,k) v=fa[v];//找到k级祖先,放置主服务器,并累加最终结果;        dfs1(v,-1,0);        ret++;    }    return ret;}int main(){    int test;    scanf("%d",&test);    while(test--)    {        scanf("%d%d%d",&n,&s,&k);        rep(i,1,n+1)        {            g[i].clear();            nodes[i].clear();        }        rep(i,0,n-1)        {            int u,v;            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        dfs(s,-1,0);        int ans=solve();        printf("%d\n",ans);    }    return 0;}


 

 

 

0 0
原创粉丝点击