【Week6作业 A】氪金带东【dfs】

题意:

原先有一台电脑(编号为1),之后又购买了N-1台电脑,编号为2到N。每台电脑都用网线连接到一台先前安装的电脑上。求每一台电脑到其他电脑的最大网线长度。
输入包含多组数据。每组数据第一行一个整数N(N<=10000),接下来有N-1行,每行两个数,对于第i行的两个数,它们表示与i号电脑连接的电脑编号以及它们之间网线的长度。网线的总长度不会超过10^9。


思路:

根据求树的直径的方法来做。求树的直径:假设树的最长路的两个叶子节点为v1,v2,从任意一点u出发走到的最远的点一定是v1,v2其中的一点。然后再从v1或者v2出发走到的最远点一定是v2或者v1。
这道题要求每一个节点所能到达的最长路径。首先每个节点的最长路径要么是到v1的路径,要么是到v2的路径。所以要先从1号点dfs求出v1或v2,然后再从v1或v2dfs求出另一个叶子(同时保存到所有点的距离),再从v2或v1dfs求出到所有点的距离。最后每个点的最远距离就是到v1、v2距离的较大值。
存图用的是邻接表,存放距离的数组为distance0至2。dfs时要把当前顶点的距离记录下来,并且vis置1。注意若用距离不为0来判断是否可以dfs会WA,这说明可能有距离为0的网线。
多组数据,还应记得清空各个数组。


总结:

一道搜索题目,想出三次遍历就能求出最长路径的思路是关键。同时应注意多组数据要清空数组,三次遍历之间也要清空vis数组。


代码:

#include <iostream>
#include <vector>
using namespace std;

struct edge
{
	int v;	//顶点 
	long long int z;	//权值 
	edge (int v1,long long int z1)
	{
		v=v1,z=z1;
	}
};
vector<edge> G[10001];	//邻接表 
bool vis[10001];	//用于dfs 
//若用距离不为0来判断dfs,会WA.说明网线会有距离为0的数据 
long long int distance0[10001];	//从顶点1开始的距离数组,用于求树的直径v1
long long int distance1[10001];	//从直径v1开始的距离数组 
long long int distance2[10001];	//从直径v2开始的距离数组 
void dfs(int v,long long int dis[],long long int distance)	//从顶点v开始dfs,顶点到v的距离记录在dis数组里
{										//distance为当前顶点到起始点的距离 
	dis[v]=distance;
	vis[v]=1;
	for(int i=0;i<G[v].size();i++)
	{
		int w=G[v][i].v;
		long long int z=G[v][i].z;
		long long int theDis=distance+z;
		if(vis[w]==0)
			dfs(w,dis,theDis);
	}
 } 
int main()
{
	int n;
	while(cin>>n)
	{
		//多组数据,应清空表
		for(int i=0;i<10001;i++)
		{
			G[i].clear();
			vis[i]=0,distance0[i]=0,distance1[i]=0,distance2[i]=0;
		 } 
		//读入数据
		for(int i=2;i<=n;i++)
		{
			int v;
			long long int z;
			cin>>v>>z;
			//顶点i与v有边,权为z
			G[i].push_back(edge(v,z));
			G[v].push_back(edge(i,z));
		} 
		//从顶点1开始dfs,求出直径顶点v1 
		dfs(1,distance0,0);
		long long int maxDis=0;
		int maxIndex=1;
		//找出distance0数组中最大距离的顶点v1
		for(int i=1;i<=n;i++)
		{
			if(distance0[i]>maxDis)
			{
				maxDis=distance0[i];
				maxIndex=i;
			}
		} 
		int v1=maxIndex;
		//从直径顶点v1开始dfs,求出到每个点的距离
		//记得清空vis
		for(int i=0;i<=n;i++)
			vis[i]=0;
		dfs(v1,distance1,0);
		//找出distance1数组中最大距离的顶点v2 
		maxDis=0,maxIndex=v1;
		for(int i=1;i<=n;i++)
		{
			if(distance1[i]>maxDis)
			{
				maxDis=distance1[i];
				maxIndex=i;
			}
		}
		int v2=maxIndex;
		//从直径顶点v2开始dfs,求出到每个点的距离
		for(int i=0;i<=n;i++)
			vis[i]=0;
		dfs(v2,distance2,0); 
		//输出n行
		for(int i=1;i<=n;i++)
		{
			int ans=distance1[i];
			if(distance2[i]>distance1[i])
				ans=distance2[i];
			cout<<ans<<endl;
		 } 
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值