p1880 [11.1]逃离迷宫

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/84501292

题目

描述 Description
小x,小y和小z,在一个迷宫里走失了。
现在他们需要汇合到一起,万幸他们通过北斗卫星得到了他们所处的位置和迷宫的地形。
迷宫可以看做一个由N个点,N-1条长度不同的双向道路组成的连通图,N个点的编号为1…N。现在知道三人的位置分别为编号x,y和z三个点上。
现在他们需要尽快的汇合,能否找到一个点,这3个人到这个点的距离之和最短。
输入格式 Input Format
第一行:四个整数N,x,y,z。表示有N个点,三个人所在点的编号。
接下来N-1行,每行三个整数,ui,vi,和wi。表示第ui点到vi点存在一条道路,道路长度为wi。
输出格式 Output Format
第一行:一个整数,表示汇合房间的编号,若存在多个点,输出编号最小的。
第二行:一个整数,表示最短的距离之和。
样例输入 Sample Input

5 3 1 4
3 5 5
4 3 9
4 1 7
1 2 1

样例输出 Sample Output

4
16

时间限制 Time Limitation
1s
注释 Hint
【数据范围】
50%数据保证  1<=N<=1000;
100% 数据保证 1<=N<=20000 ,1≤x,y,z,ui,vi<=N且x,y,z肯定不相等;ui,vi不相等。  
1≤wi≤1,000。

【友情提示】
树是一种特殊的连通图,N个点,N-1条边,且肯定连通,任意两点有且仅有一条路径相通。

题解

1.建立三个dist数组,分别记录x,y,z到各点的距离,
2.跑三次dfs,分别算出x,y,z到各点的距离,(就和普通的dfs一样,只不过加一个计算距离的代码即可,就像这样:)

void dfs3(int x)
{
	v[x]=1;
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i],z=edge[i];
		if (!v[y])
		{
			d3[y]=d3[x]+z;
			v[y]=1,dfs3(y);
		}
	}
}

3.用一个for循环枚举距离之和,记录最短距离和为minn,此点的位置为id。

好了,请出代码

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int f=1,num=0;
	char ch=getchar();
	while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
	while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
	return num*f;
}
const int _=110000;
const int inf=99999999;
int n,num1,num2,num3;
int d1[_],d2[_],d3[_],id=0,minn=100000000,sum=0;
int ver[_],edge[_],Next[_],head[_],len;
void add(int x,int y,int z)
{
	ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
bool v[_];
void dfs1(int x)
{
	v[x]=1;
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i],z=edge[i];
		
		if (!v[y])
		{
			d1[y]=d1[x]+z;
			v[y]=1,dfs1(y);
		}
	}
}void dfs2(int x)
{
	v[x]=1;
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i],z=edge[i];
		if (!v[y])
		{
			d2[y]=d2[x]+z;
			v[y]=1,dfs2(y);
		}
	}
}void dfs3(int x)
{
	v[x]=1;
	for (int i=head[x];i;i=Next[i])
	{
		int y=ver[i],z=edge[i];
		if (!v[y])
		{
			d3[y]=d3[x]+z;
			v[y]=1,dfs3(y);
		}
	}
}
int main()
{
	n=read(),num1=read(),num2=read(),num3=read();
	for (int i=1;i<n;++i)
	{
		int a=read(),b=read(),c=read();
		add(a,b,c),add(b,a,c);
	}
	dfs1(num1);
	memset(v,0,sizeof(v));
	dfs2(num2);
	memset(v,0,sizeof(v));
	dfs3(num3);
	for (int i=1;i<=n;++i)
	{
		sum=d1[i]+d2[i]+d3[i];
		if (sum<minn) id=i,minn=sum;
	}
	printf("%d\n%d",id,minn);
	return 0;
}

小结

当我刚看到题时,一看见“最短路之和”,便什么也不想,直接写了个SPFA,结果。。。。。。。。。。就炸了。。。。。。在大佬的指点下,我才看见这竟然 是一棵树。。。。。。。。。。只要dfs就行了。。。。。
今天常神又来问我有无水题可做,我便向他推荐了这道题,结果,他直接就想到了思路,然后,然后,就A了。。。。。。。。。。不愧是大佬啊!!!!!!!%%%%%%%%%%orz

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/84501292