#include<stdio.h> //I love PKU
#include<string.h>
#include<stdlib.h>
#define INFINITE 9999999
#define MaxVexnum 30 //顶点的最大个数
#define MaxArcnum 50 //边的最大个数
typedef struct graph
{
int vexnum, arcnum;
char *vexname[MaxVexnum];
int Matrix[MaxVexnum][MaxVexnum];
}Graph;
void getvex(Graph *G)
{
int i, Vexnum;
char temp[21];
scanf("%d", &Vexnum);
G->vexnum = Vexnum;
for (i = 0; i < G->vexnum; i++)
{
G->vexname[i] = (char *)malloc(sizeof(char));
scanf("%s", G->vexname[i]);
}
}
int locatevex(Graph *G, char *name)
{
int i;
for (i = 0; i < G->vexnum; i++)
{
if (strcmp(G->vexname[i], name) == 0)
return i;
}
exit(0);
}
void create_graph(Graph *G)
{
int i, j, k, weight, Arcnum;
char s1[21], s2[21];
getvex(G);
for (i = 0; i < G->vexnum; i++)
for (j = 0; j < G->vexnum; j++)
{
if (i == j) G->Matrix[i][j] = 0;
else G->Matrix[i][j] = INFINITE;
}
scanf("%d", &Arcnum);
G->arcnum = Arcnum;
for (k = 0; k < G->arcnum; k++)
{
scanf("%s", s1);
scanf("%s", s2);
scanf("%d", &weight);
i = locatevex(G, s1);
j = locatevex(G, s2);
if (weight<G->Matrix[i][j]) //处理一些特殊的数据,同一条边多次出现,权值取最小的
G->Matrix[i][j] = G->Matrix[j][i] = weight; //无向图
}
}
void floyd(Graph *G, int path[][MaxVexnum], int dis[][MaxVexnum]) //弗洛伊德算法所有两两顶点最短路径
{
int i, j, k;
for (i = 0; i<G->vexnum; i++)
for (j = 0; j<G->vexnum; j++)
{
dis[i][j] = G->Matrix[i][j];
if (dis[i][j]<INFINITE)
path[i][j] = i; //表示从i到j必须经过i
else
path[i][j] = -1;
}
for (k = 0; k<G->vexnum; k++) //k表示第k次试探,求得的是从vi到vj中间顶点的序号不大于k的路径
for (i = 0; i<G->vexnum; i++)
for (j = 0; j<G->vexnum; j++)
{
if (dis[i][j]>(dis[i][k] + dis[k][j]))
{
dis[i][j] = dis[i][k] + dis[k][j];
path[i][j] = path[k][j]; //path[i][j]=path[j][k]可以保证此时的path[i][j]即为从i到j所必须经过的点,
//并且该点是距离j最近的点,在恢复路径时只需不断向前找直到到达顶点i即可,
//而如果用path[i][j]=k可能遗失掉(k,j)之间的点,即此时的k不一定是距离i
//最近的点,不利用恢复路径
}
}
}
void print_dis(Graph *G, int path[][MaxVexnum], int dis[][MaxVexnum], char *start, char *end)
{
int i, j, k, t;
i = locatevex(G, start);
j = locatevex(G, end);
if (i == j)
{
printf("%s\n", end);
return;
}
printf("%s", G->vexname[i]);
k = path[j][i]; //由于path中为i到j的逆路径,因此输出时输出从j到i的路径
t = i; //t为路径中k的后继
while (k != j)
{
printf("->(%d)->", G->Matrix[k][t]);
printf("%s", G->vexname[k]);
t = k;
k = path[j][k];
}
printf("->(%d)->", G->Matrix[t][k]);
printf("%s\n", G->vexname[j]);
}
int main()
{
Graph G;
int dis[MaxVexnum][MaxVexnum], path[MaxVexnum][MaxVexnum];
char start[21], end[21];
int N, i;
create_graph(&G);
floyd(&G, path, dis);
scanf("%d", &N);
while (N--)
{
scanf("%s", start);
scanf("%s", end);
print_dis(&G, path, dis, start, end);
}
return 0;
}
DSOJ I Love PKU(我爱北大)
最新推荐文章于 2023-05-24 23:04:17 发布