码迷,mamicode.com
首页 > 其他好文 > 详细

[HDU4607]Park Visit(树上最长链)

时间:2017-10-09 18:31:01      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:输出   put   while   iostream   wal   遍历   test   algorithm   多少   

先附上原题:

HDU#4607. 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?
 

输入格式

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≤105), 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.
 

输出格式

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

样例输入输出

输入

1 4 2 3 2 1 2 4 2 2 4

  

输出

1 4

  

题意:

给定一棵树,从树中的任意选一个顶点出发,遍历K个点的最短距离是多少?(每条边的长度为1)
 

分析:

 
很自然的联想到求一遍最长链。设最长链长度为len
如果K < len + 1,那么答案就为K - 1,因为只需在最长链上走就行了。
如果K > len + 1;那么肯定不能不重复的遍历完K个点,一定有些点会重复遍历。这样就有些点的子树需要重复遍历,我们肯定不会去选取最长链重复遍历。
就是最长链上的点为根,不包含最长链的子树重复遍历。那么答案就变成了 len + (K - len - 1) * 2
 
 

 

树上最长链:

 
 求树上最长链的方法是用dp来求的。
f1表示从一个点子树里的最长链,f2表示一个点子树里的次长链。维护一下,然后答案为每个点f1 + f2的之中的最大值
int dfs(int u,int pre){
        for(int i = head[u];i;i = edge[i].next){
                int v = edge[i].to;
                if(v == pre)continue;
                dfs(v,u);
                if(f1[u] < f1[v] + edge[i].dis)
        {
            f2[u] = f1[u];
            f1[u] = f1[v] + edge[i].dis;
        }
        else    f2[u] = max(f2[u],f1[v] + edge[i].dis);
        }
        ans = max(ans,f1[u] + f2[u]);
        return ans;
}

 

贴上AC代码:

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
const int N = 1e5 + 10002;
const int M = 2e5 + 10002;
const int INF = 0x3f3f3f3f;
int n,m,cnt,head[N];
int read()
{
int ans=0,f=1;
char i=getchar();
while(i<‘0‘||i>‘9‘){if(i==‘-‘)f=-1;i=getchar();}
while(i>=‘0‘&&i<=‘9‘){ans=ans*10+i-‘0‘;i=getchar();}
return ans*f;
}
struct Edge{
int to,next;
int dis;
}edge[M];
void AddEdge(int u,int v,int res){
Edge E1 = {v,head[u],res};
edge[++cnt] = E1;head[u] = cnt;
Edge E2 = {u,head[v],res};
edge[++cnt] = E2;head[v] = cnt;
}
long long f1[N],f2[N],ans;
int dfs(int u,int pre){
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u);
if(f1[u] < f1[v] + edge[i].dis)
{
f2[u] = f1[u];
f1[u] = f1[v] + edge[i].dis;
}
else f2[u] = max(f2[u],f1[v] + edge[i].dis);
}
ans = max(ans,f1[u] + f2[u]);
return ans;
}
void Init(){
memset(head,0,sizeof head);
memset(f1,0,sizeof f1);
memset(f2,0,sizeof f2);
cnt = ans = 0;
}
void Getmap(){
Init();
n = read(), m = read();
int x,y,z;
for(int i = 1;i < n;i++){
x = read();y = read();
AddEdge(x,y,1);
}
dfs(1,-1);
ans += 1;
for(int i = 1;i <= m;i++){
x = read();
if(x <= ans)printf("%d\n",x - 1);
else printf("%d\n",ans - 1 + (x - ans) * 2);
}
}
int main(){
int T;
T = read();
while(T--)
Getmap();
return 0;
}

  

[HDU4607]Park Visit(树上最长链)

标签:输出   put   while   iostream   wal   遍历   test   algorithm   多少   

原文地址:http://www.cnblogs.com/lzdhydzzh/p/7642134.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!