求一个点到另外两个点的最短距离 中间重复路径只算一次
解题思路:
三次迪杰斯特拉 先求出三个点到各个顶点的最短距离,分别记录在三个数组中,在一次遍历这三个数组求task1[i]+task2[i]+task3[i]最小的值为所求,如果如果没有最小值则表示不能到达
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxnum 5005
int map[maxnum][maxnum];
int n,m,task1[maxnum],task2[maxnum],task3[maxnum];
int sign[maxnum];
int n1,n2,n3;
void solve(int ni,int task[])
{
int i,j,u,min;
memset(sign,0,sizeof(sign));
sign[ni]=1;
for(i=1;i<=n;i++)
task[i]=map[ni][i];
for(i=1;i<=n;i++)
{
min=0xfffffff;
u=-1;
for(j=1;j<=n;j++)
if(!sign[j]&&min>task[j])
{
min=task[j];
u=j;
}
if(min==0xfffffff) break;
sign[u]=1;
for(j=1;j<=n;j++)
{
if(!sign[j]&&task[j]>task[u]+map[u][j])
{
task[j]=task[u]+map[u][j];
}
}
}
}
int getresult()
{
int i;
int min=0xfffffff;
task1[n1]=0;
task2[n2]=0;
task3[n3]=0;
for(i=1;i<=n;i++)
{
if(task1[i]+task2[i]+task3[i]<min)
min=task1[i]+task2[i]+task3[i];
}
if(min<0xfffffff)
return min;
return -1;
}
int main()
{
int i,j,x,y,len,mi;
int k=0;
while(scanf("%d%d",&n,&m)!=EOF)
{
k++;
scanf("%d%d%d",&n1,&n2,&n3);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
map[i][j]=0xfffffff;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&len);
map[x][y]=map[y][x]=len;
}
solve(n1,task1);
solve(n2,task2);
solve(n3,task3);
printf("Scenario #%d\n",k);
mi=getresult();
if(mi!=-1)
printf("%d\n\n",mi);
else
printf("Can not reach!\n\n");
}
return 0;
}