您的位置:首页 > 其它

hdu4607:Park Visit

2014-11-15 16:19 666 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607

参考思路:题目的大意就是给定一颗有n个节点的树,每条边长度为1,然后需要采访k个节点,可以以任意一点为起始节点,问采访完k个节点所走的路径最短为多少。

如果我们知道了树里面距离最远的节点的距离为maxLength,那么我们沿着这条主路径走,如果这条主路径的节点数maxLength+1不够k个,那么我们就在主路径旁边选节点直到够k个,最短路径为maxLength + 2*(k-1 - maxLength)。

源代码:

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include <string>
#include <cstdio>
#include <map>
#include <queue>

using namespace std;

const int inf = 0x7fffffff;

typedef __int64 lld;

inline int myMin(int a, int b) {
return a < b ? a : b;
}

inline int myMax(int a, int b) {
return a > b ? a : b;
}

#define MOD 1000000007;

vector<int> vi[100001];//树
int help[100001];//help[i]表示已i为根的子树里面深度最大的节点的深度
int n, m;

//得到help[index]
void getHelp(int index, int father) {
if(vi[index].size() == 1 && vi[index][0] == father) {//为叶子节点
help[index] = 0;
} else {
vector<int>::iterator it = vi[index].begin();
int temp = 0;
while(it != vi[index].end()) {
if(*it != father) {
getHelp(*it, index);
temp = myMax(temp, help[*it]);
}
it++;
}
help[index] = temp + 1;
}
}

//得到已index节点为根的子树里面相距最远的节点的距离
int dfs(int index, int father) {
if(vi[index].size() == 1 && vi[index][0] == father) {
return 0;
}
int result = 0;
vector<int>::iterator it = vi[index].begin();
//不经过index节点
int temp = 0, cnt = 0;//cnt记录index的孩子个数
while(it != vi[index].end()) {
if(*it != father) {
cnt++;
temp = myMax(temp, dfs(*it, index));
}
it++;
}
result = temp;
//经过index节点
if(cnt == 1) {//只有一个孩子
it = vi[index].begin();
while(it != vi[index].end()) {
if(*it != father) {
return myMax(result, help[*it] + 1);
}
it++;
}
} else {//大于等于两个孩子
int max1 = 0, max2 = 0;
it = vi[index].begin();
while(it != vi[index].end()) {
if(*it != father) {
if(help[*it] > max1) {
max2 = max1;
max1 = help[*it];
} else {
if(help[*it] > max2) {
max2 = help[*it];
}
}
}
it++;
}
return myMax(result, max1 + max2 + 2);
}
}

int work() {
getHelp(1, -1);

return dfs(1, -1);
}

int main()
{
int t;
scanf("%d", &t);
for(int ca=1; ca<=t; ca++) {
scanf("%d%d", &n, &m);
int i, j;
for(i=1; i<=n; i++) {
vi[i].clear();
}
while(--n) {
int u, v;
scanf("%d%d", &u, &v);
vi[u].push_back(v);
vi[v].push_back(u);
}
int maxLength = work();
while(m--) {
int num;
scanf("%d", &num);
if(num-1 <= maxLength) {
printf("%d\n", num-1);
} else {
printf("%d\n", (num-1-maxLength)*2 + maxLength);
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: