HUNAN 11532 Touring

求一个点到另外两个点的最短距离 中间重复路径只算一次

解题思路:

三次迪杰斯特拉 先求出三个点到各个顶点的最短距离,分别记录在三个数组中,在一次遍历这三个数组求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;
}

你可能感兴趣的:(n2)