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