Network UVALive - 3902 网络 树的链接

版权声明:本文为博主原创文章,未经博主允许不得转载,欢迎添加友链。 https://blog.csdn.net/qq_42835910/article/details/89764808

题目链接 

Consider a tree network with n nodes where the internal nodes correspond to servers and the terminalnodes correspond to clients. The nodes are numbered from 1 to n. Among the servers, there is anoriginal server S which provides VOD (Video On Demand) service. To ensure the quality of service forthe 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 dened 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, nd 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. In the above tree, the set of clients is f1, 6, 7, 8, 9, 10, 11, 13g, the set of servers is f2, 3, 4, 5, 12, 14g, 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 f6, 7, 8, 9, 10g 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 f12, 4g is less than or equal to 2. The minimum number of the needed replicas is one for this example.

分析:首先以已知服务器节点为根节点将无根树变成有根树,然后记录未能服务的的叶子结点的深度,从深度最大的节点考虑,并在他的k级祖先安装服务器,使之链接最大化。

#include <cstdio> 
#include <vector>
#include <cstring>
using namespace std;
const int N = 1000 + 5;
vector<int> node[N], g[N];
bool covered[N];
int n, s, k, fa[N]; // reserve father node
// 无根树转有根树,计算fa数组,根据深度把叶子节点插入node表里 
void dfs(int u,int f,int d){
	fa[u] = f;
	int size =  g[u].size();
	if(size == 1 && d > k) node[d].push_back(u); //未得到服务的叶子节点  
	for(int i = 0; i < size; i++){
		int v = g[u][i];
		if(f != v)  dfs(v, u, d+1);		
	}
}

void dfs2(int u,int f,int d){
	covered[u] = true;
	for(int i = 0; i < g[u].size(); i++){
		int v = g[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 < node[d].size(); i++){
			int v = node[d][i];
			if(covered[v]) continue; //不考虑已覆盖结点 
			int f = v;
			for(int j = 0; j < k; j++) //f是v的k级祖先 
				f = fa[f];
			dfs2(f, -1, 0);
			ans++;
		}
	}
	return ans;
}

int main(int argc, char** argv) {
	int T;
	scanf("%d",&T);
	while(T--){		
		scanf("%d%d%d",&n,&s,&k);
		for(int i = 1; i <= n; i++){
			g[i].clear();
			node[i].clear();
		}
		for(int i = 0; i < n-1; i++){
			int a, b;
			scanf("%d%d",&a,&b);  
			g[a].push_back(b);
			g[b].push_back(a);	
		}
		dfs(s, -1, 0);
		printf("%d\n", solve());
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42835910/article/details/89764808
今日推荐