uva1267 - Network 无根树转化有根树 树形DFS

来源:互联网 发布:魔兽世界国服mac版 编辑:程序博客网 时间:2024/06/08 14:30

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 ton . Among the servers, there is an original serverS which provides VOD (Video On Demand) service. To ensure the quality of service for the clients, the distance from each client to the VOD serverS should not exceed a certain value k . The distance from a node u to a nodev in the tree is defined to be the number of edges on the path fromu tov . If there is a nonempty subsetC of clients such that the distance from eachu inC toS is greater thank , 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) isk or less.

Given a tree network, a server S which has VOD system, and a positive integerk , find the minimum number of replicas necessary so that each client is within distancek 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 integern(3$ \le$n$ \le$1, 000) which is the number of nodes of the tree network. The next line contains two integerss(1$ \le$s$ \le$n) andk(k$ \ge$1) wheres is the VOD server andk is the distance value for ensuring the quality of service. In the followingn - 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


  这时第一次写树形DFS。。

  N个结点连成树状网络,叶结点是客户端,其他结点结点可以放服务器。目前已经有一个服务器S。问要使所有客户端到服务器的距离不大于K,最少还需要放多少个服务器。

  思路是先把这个图变成一个有根树(DFS,把父结点的每个子结点分别建树),深度为d的叶子保存在容器node[d]中,u的父亲结点保存在fa[u]中。深度小于K的叶子已经被原有服务器覆盖,不需要再考虑。解决这个问题的方法是深度从大到小遍历叶子(如果从小往大就不能确定设立在哪个点),如果有叶子u没被覆盖,就选择在u的K级祖先放服务器,这样是最划算的(因为u没被覆盖,在u的K级祖先以内的点肯定是要放一个,如在小于K的m级祖先的某个子树的位置放,因为目前的叶子是最深的,子树的深度肯定不会超过它,所以这个位置能覆盖到的K级祖先也一定能覆盖到,并且K级祖先可能覆盖到上面的更多地方)。这时就要通过K次循环fa[u]找到K级祖先这个点了。找到这个点后,DFS把周围距离不大于K的都标记覆盖。然后设立点加1。

  在树上不用标记访问数组。DFS时判断条件只要v!=f,也就是从父结点找到子结点,子结点不回到父结点就行了,只要不回到父结点就肯定不会到以前访问过的点,因为树是没有环的。


#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#include<queue>#include<map>#define INF 0x3f3f3f3f#define MAXN 1010#define MAXM 20010#define eps 1e-9#define pii pair<int,int>using namespace std;int T,N,S,K,fa[MAXN],covered[MAXN];vector<int> gr[MAXN],node[MAXN];void build(int u,int f,int dep){   //建立有根树    fa[u]=f;    int L=gr[u].size();    if(L==1&&dep>K) node[dep].push_back(u);  //深度小于K的可以忽略    for(int i=0;i<L;i++){        int v=gr[u][i];        if(v!=f) build(v,u,dep+1);    }}void DFS(int u,int f,int dep){   //把要放置的点距离不大于K的都标记    covered[u]=1;    int L=gr[u].size();    for(int i=0;i<L;i++){        int v=gr[u][i];        if(v!=f&&dep<K) DFS(v,u,dep+1);    }}int solve(){    int u,ret=0;    memset(covered,0,sizeof(covered));    for(int d=N-1;d>K;d--){        for(int i=0;i<node[d].size();i++){            u=node[d][i];            if(covered[u]) continue;            for(int i=0;i<K;i++) u=fa[u];            DFS(u,-1,0);            ret++;        }    }    return ret;}int main(){    freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--){        for(int i=1;i<=N;i++){            gr[i].clear();            node[i].clear();        }        scanf("%d%d%d",&N,&S,&K);        int u,v;        for(int i=0;i<N-1;i++){            scanf("%d%d",&u,&v);            gr[u].push_back(v);            gr[v].push_back(u);        }        build(S,-1,0);        printf("%d\n",solve());    }    return 0;}


0 0
原创粉丝点击