求最短路径Dijkstra,反向建边。
注意初始位置和目标位置相同时,最短路径上只有一个交叉路口。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 100000
#define MAX 21
using namespace std;
struct Node{
int index;
int dis;
bool operator <(const Node &b)const
{
return dis<b.dis;
}
};
Node orgn[MAX];
int n;
int dist[MAX];
int edge[MAX][MAX];
int path[MAX];
int s[MAX];
void Dijkstra(int v0)
{
int i,j,k;
for(i=1; i<=n; i++)
{
dist[i]=edge[v0][i] ;
s[i]=0;
if(i!=v0&&dist[i]<INF)path[i]=v0;
else path[i]=-1;
}
s[v0]=1,dist[v0]=0;
for(i=0; i<n-1; i++)
{
int min=INF;
int u=v0;
for(j=1; j<=n; j++)
{
if(!s[j]&&dist[j]<min)
{
min=dist[j];
u=j;
}
}
s[u]=1;
for(k=1; k<=n; k++)
{
if(!s[k]&&edge[u][k]<INF&&dist[u]+edge[u][k]<dist[k])
{
dist[k]=dist[u]+edge[u][k];
path[k]=u;
}
}
}
}
int main()
{
bool flag=0;
int T,dest;
int i,j;
char org[21];
cin>>T;
while(T--)
{
cin>>n;
getchar();
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
cin>>edge[i][j];
if(edge[i][j]==-1)edge[i][j]=INF;
}
for(i=1;i<=n;edge[i][i]=0,i++)
for(j=i+1;j<=n;j++)
swap(edge[i][j],edge[j][i]);
gets(org);
gets(org);
dest=org[0]-'0';
int k=0;
for(i=2; i<strlen(org); i+=2)
{
orgn[k++].index=org[i]-'0';
}
Dijkstra(dest);
if(flag)cout<<endl;
else flag=true;
for(i=0; i<k; i++)
{
orgn[i].dis=dist[orgn[i].index];
}
sort(orgn,orgn+k);
printf("Org\tDest\tTime\tPath\n");
for(i=0; i<k; i++)
{
int temp=orgn[i].index;
printf("%d\t%d\t%d\t%d",temp,dest,dist[temp],temp);
if(dest==temp)
{printf("\n");
continue;
}
while(path[temp]!=dest)
{
printf("\t%d",path[temp]);
temp=path[temp];
}
printf("\t%d\n",dest);
}
}
return 0;
}