Asia - Seoul - 2007/2008 UVA 3902 Network

来源:互联网 发布:迅捷数据恢复注册码 编辑:程序博客网 时间:2024/06/05 15:26
3902 - Network
Asia - Seoul - 2007/2008PDF Submit Ranking

 

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 S which 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
大致的意思就是给定一棵树,有根S,作为服务端,所有的叶子节点作为客户端,现在给定一个k,让你把最少的节点变成服务端,
使得对于每个叶子点到最近的服务端节点距离<=k
分析:我们对这棵树进行dfs遍历,对于任何一个访问到的点x,他必定有两个状态,设置成服务端,不设成服务端,
那么什么时候设置成服务端呢?,当以x为根的子树中,存在一个最远的尚未分配的叶子节点,到当前点的距离为k时,
那么此时的x必须要设成服务端,这时候对于从祖先方向过来的叶子也存在被当前点匹配的情况,于是我们要
再记录一个东西来保存到当前点为根的子树最近的服务端的距离,这个就叫不要白不要,
连同之前的就保证了每次都到万不得已才添加新的服务端点,顺便带走几个可以匹配的点
那么我们现在就有了一个基本的算法流程
(1)以S为根,对树做dfs遍历
(2)如果当前点是叶子且到S距离<=k,那么对这一系列情况都特判掉
(3)遍历以x为根的孩子
     如果当前孩子有未匹配的,记录下最大的那个
     如果当前子树存在服务端,记录下离当前最近的那个
(4)若x当前未分配
    若距离>=k 则计数器++
    表示x设定为服务端
    否则若当前点距离到最近服务端距离<=k,那么匹配掉
 
C++ CODE   :No Title Code
 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
#include<iostream>#include<cstdio>#include<vector>#include<bitset>#include<cstring>using namespace std;const int maxn=1005,INF=1000000000;vector<int>v[maxn];int n,dp[maxn],way[maxn],dist[maxn],ans,root,lim;//dist[x]表示以x为根,最远的叶子离他的距离,如果dist[x]=-1且way[x]==1表示该叶子已经分配好了//dp[x]表示离x最近的服务站的距离,初始为INF void dfs(int x,int pr,int deep){    if(x!=root&&way[x]==1){//当前是叶子,且不是根        if(deep<=lim)dist[x]=-1;       else dist[x]=0;       dp[x]=INF;       return ;                           }     dist[x]=-1;    dp[x]=INF;    for(int i=0;i<v[x].size();i++){        int y=v[x][i];        if(y!=pr){           dfs(y,x,deep+1);           if(dist[y]!=-1)dist[x]=max(dist[x],dist[y]+1);                  if(dp[y]!=INF)dp[x]=min(dp[x],dp[y]+1);              }            }    if(dist[x]!=-1){//以x为根的子树存在未分配的叶子        if(dist[x]>=lim){          ans++;          dist[x]=-1;          dp[x]=0;                        }              else if(dist[x]+dp[x]<=lim)dist[x]=-1;                }          }int main(){    int test;    cin>>test;    while(test--){          cin>>n;          cin>>root>>lim;          for(int i=1;i<=n;i++){              v[i].clear();              way[i]=0;               }                  for(int i=1;i<n;i++){              int x,y;                  cin>>x>>y;              way[x]++;way[y]++;              v[x].push_back(y);              v[y].push_back(x);                  }              ans=0;              dfs(root,root,0);          cout<<ans<<endl;              }    return 0;    }/*10111 21 21 31 1111 44 54 66 76 97 89 10*/
原创粉丝点击