杭电 4607 Park Visit

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4607

大意是,给你一个连通图(根据题意其实就是一棵树),N个点,问访问K个点最少需要走几条边。

是一个学弟问我的,很惭愧,真心不会,没做过类似的最短路径。

上网查了一下,才知道是求这个图的最大直径。

参考的是这个帖子,讲的还可以,代码也比较容易懂:http://www.cnblogs.com/0803yijia/p/3209371.html

代码粘一下吧,一模一样的,不过这个证明还真是挺意外的:

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;

const int N=111111;
int m,n;

vector<int>vec[N];
struct node
{
	int s;
	int point;
};
int vis[N];

node bfs(int s)
{
	memset(vis,0,sizeof(vis));
	queue<node>q;
	node tmp;
	tmp.s=0;
	tmp.point=s;
	q.push(tmp);
	vis[s]=1;
	node Max;
	Max.s=0;

	while(!q.empty())
	{
		node now,temp;
		now=q.front();
		q.pop();
		for(int i=0;i<vec[now.point].size();i++)
		{
			int v=vec[now.point][i];
			temp.s=now.s+1;
			temp.point=v;
			if(!vis[v])
			{
				vis[v]=1;
				if(Max.s<temp.s)
					Max=temp;
				q.push(temp);
			}
		}
	}
	return Max;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
	scanf("%d %d",&n,&m);
	for(int i=0;i<=n;i++)
		vec[i].clear();
	for(int i=1;i<n;i++)
	{
		int a,b;
		scanf("%d %d",&a,&b);
		vec[a].push_back(b);
		vec[b].push_back(a);
	}
	node Max;
	Max=bfs(1);
	Max=bfs(Max.point);

	for(int i=0;i<m;i++)
	{
		int k;
		scanf("%d",&k);
		if(k<=Max.s+1)
			printf("%d\n",k-1);
		else
			printf("%d\n",(k-Max.s-1)*2+Max.s);
	}
	}
	return  0;
}


你可能感兴趣的:(杭电,visit,park,4607)