机器选择【树】【DFS】

>Description
机房有n台机器,且有局域网,所有机器通过一些网线连接起来,其整个布局是一个树形结构,即任意两台机器间都有且仅有一条路径。小T想在其中某一台机器上储存这个文件,需要的同学就可以直接通过局域网来下载这个文件。
网络上信息传输是需要时间的,我们定义两台机器间数据传输的时间为连接这两台机器的路径所包含的网线数量。虽然机房里通过局域网传个文件是很快的,但对于急不可耐的同学们来说,一分一秒都是宝贵的,文件传输越快越好。所以小T要选择一台机器存储文件,使得所有机器下载这个文件需要的总时间(即最后一台机器完成下载的时间)尽可能短。
现在,你需要给出这个最短时间,以便让小T看看他的决策是否最优。


>Input
第1行:一个整数n。
第2n行:两个整数u、v,即u、v两台机器间有一条网线连接。机器从1n编号。
输入数据保证是一个连通的树型结构。

>Output
1行一个整数,即最短的时间。


>Sample Input
5
3 2
2 1
5 2
2 4

>Sample Output
1


解题思路
先找出树的直径(也就是最远的两点间的距离),然后在树的直径的路径上截取一点使这一点到最远的距离最短(其实只用把树的直径/2就行了,但是为了避免树的直径是奇数然后出错,所以还要加上树的直径%2)

如何实现:
确定一号点(任意一点),找到离一号点最远的一个二号点,然后在找到离二号点最远的一个三号点,树的直径就是二号点与三号点之间的距离。

其实也可以用另一个邻接表的方法来做,我一开始用的就是这个方法,但是不知道为什么没有A。


>代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct ooo
{
	int to,next;
}a[200005];
int n,x,y,h[100005],t,ans,k;
bool lhq[100005];
char c;
void lil(int aa,int s) //aa为当前节点,s为长度
{
	lhq[aa]=1; //标记已经走过
	if(s>ans)
	{
		ans=s; k=aa;
	}
	for(int i=h[aa];i;i=a[i].next)
	 if(!lhq[a[i].to]) lil(a[i].to,s+1);
	lhq[aa]=0; //回溯(第二次找三号点的时候还要用)
}
int main()
{
	int size = 256 << 20;
    char*p=(char*)malloc(size) + size;
    __asm__("movl %0, %%esp\n" :: "r"(p) );//(鬼知道)要加这个东西才能A
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		a[++t].to=y; a[t].next=h[x]; h[x]=t;
		a[++t].to=x; a[t].next=h[y]; h[y]=t;
	}
	lil(1,0);
	lil(k,0);
	printf("%d",ans/2+ans%2);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/88717110