设为首页 加入收藏

TOP

Park Visit(树型DP)
2017-06-15 10:22:34 】 浏览:8704
Tags:Park Visit 树型

Park Visit

 Claire and her little friend, ykwd, are travelling in Shevchenko's Park! The park is beautiful - but large, indeed. N feature spots in the park are connected by exactly (N-1) undirected paths, and Claire is too tired to visit all of them. After consideration, she decides to visit only K spots among them. She takes out a map of the park, and luckily, finds that there're entrances at each feature spot! Claire wants to choose an entrance, and find a way of visit to minimize the distance she has to walk. For convenience, we can assume the length of all paths are 1.
Claire is too tired. Can you help her?

Input

An integer T(T≤20) will exist in the first line of input, indicating the number of test cases. Each test case begins with two integers N and M(1≤N,M≤10 5), which respectively denotes the number of nodes and queries. The following (N-1) lines, each with a pair of integers (u,v), describe the tree edges. The following M lines, each with an integer K(1≤K≤N), describe the queries. The nodes are labeled from 1 to N. 

Output

For each query, output the minimum walking distance, one per line. 

Sample Input

1 4 2 3 2 1 2 4 2 2 4 

Sample Output

1 4 

题目大意:

莱克尔和她的朋友到公园玩,公园很大也很漂亮。公园包含n个景点通过n-1条边相连。克莱尔太累了,所以不能去参观所有点景点。经过深思熟虑,她决定只访问其中的k个景点。她拿出地图发现所有景点的入口都很特殊。所以她想选择一个入口,并找到一条最短的路来参观k个景点。假设景点之间的距离为1。

输入数据:先输入测试用例数t,每个测试用例数据包括N和M,N为节点数,M为需要查询的上述的k(参观M个景点)。

输出数据:对于各个M,输出需要走的距离。

题目解析:

这道题目需要求走的最短距离,而我们知道由于每一个点都有入口,所以我们只需要求出这棵树的最长链,因为只要我们需要访问的个数小于等于最长链的长度,那么也就只需要走k-1步就足够了,即使大于了最长链也仅仅需要(k-len)*2 + len - 1步便可以走完。只需要把多出来的那几步来回走一遍就可以了。

求最长链的方法:

方法一:利用dfs或者bfs随便选取一个点s开始,找到他的最远点u,再从最远点u开始第二次搜索找到u的最远点v,此时u到v的距离就是这颗树的最长链。

方法二:使用树形dp,首先随便从一个点开始搜,递归查询每个点,定义 f[i][0] 为从i号节点往下的最大深度,定义 f[i][1] 为从i号节点往下的次大深度。递归求出 f[i][0] f[i][1] 。再定义 dp[i] 为过节点i的最长链长度,递归求解。

代码如下:

#include 
       
         #include 
        
          #include 
         
           using namespace std; const int maxn = 200000 + 5; struct Edge{ int next,to; }G[maxn]; int n,m; int head[maxn],cnt; int f[maxn][2],dp[maxn]; void Insert(int u,int v){ G[++cnt].next = head[u]; G[cnt].to = v; head[u] = cnt; } int sign[maxn],vis[maxn]; void dp1(int u){ sign[u] = 1; for(int e = head[u];e;e = G[e].next){ int v = G[e].to; if(!sign[v]){ dp1(v); if(f[v][0] + 1 > f[u][0]){ f[u][0] = f[v][0] + 1; vis[u] = v; } } } for(int e = head[u];e;e = G[e].next){ int v = G[e].to; if(vis[u] != v){ f[u][1] = max(f[u][1],f[v][0]+1); } } } void dp2(int u){ sign[u] = 1; for(int e = head[u];e; e = G[e].next){ int v = G[e].to; if(!sign[v]){ if(vis[u] == v)dp[v] = max(dp[u],f[u][1]) + 1; else dp[v] = max(dp[u],f[u][0])+1; dp2(v); } } } int main(){ int T,u,v; scanf("%d",&T); while(T--){ memset(dp,0,sizeof(dp)); memset(f,0,sizeof(f)); memset(vis,0,sizeof(vis)); memset(sign,0,sizeof(sign)); memset(head,0,sizeof(head)); cnt = 0; scanf("%d%d",&n,&m); for(int i = 0;i < n-1; i++){ scanf("%d%d",&u,&v); Insert(u,v); Insert(v,u); } dp1(1); memset(sign,0,sizeof(sign)); dp2(1); int len = 0; for(int i = 1;i <= n; i++){ len = max(len,max(f[i][0],dp[i])); } len++; while(m--){ int k; scanf("%d",&k); if(k <= len)printf("%d\n",k-1); else printf("%d\n",len-1+(k-len)*2); } } } 
         
        
       
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇c++装饰模式 下一篇BP神经网络

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目