1. 程式人生 > >p1880 [11.1]逃離迷宮

p1880 [11.1]逃離迷宮

題目

描述 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