数据结构-带权无向图-最短路径(弗洛伊德算法)

 注:本文采用Floyd算法求每个结点到其他结点的最短路径,要注意的是选每个结点到其他结点最远路径中最短的一个村庄!!!

Description

题目内容:有n个村庄,现要选择在一个村庄中建立一所医院,使得该医院到离其最远的村庄,距离最近。

说明: 输入第一行为村庄数;第二行为各村庄名;第三行至最后为各村庄的距离。

输出为:所选医院所在的村庄。

本题假设选址是唯一的,不考虑多解。

Sample Input

4

A B C D

A B 8

A D 6

B C 4

B D 5

C D 3

Sample Output

D

Hint

输出有换行符

#include <bits/stdc++.h>
#define Max_size 105
#define INTSIZE 32576
using namespace std;
// 邻接矩阵
typedef struct Arcell
{
    int adj;
} Arcell, adjMa[Max_size][Max_size];
typedef struct
{
    char vexs[Max_size];
    adjMa arcs;
    int vex, arc;
} MG;
int locatevex(MG G, char ch)
{ // 查找下标
    for (int i = 1; i <= G.vex; i++)
    {
        if (G.vexs[i] == ch)
            return i;
    }
}
void creatMG(MG &G)
{ // 创建带权无向图
    int n, j, k, info;
    char v1, v2;
    cin >> n;
    G.vex = n;
    for (int i = 1; i <= n; i++)
    { // 输入
        cin >> G.vexs[i];
        for (int j = 1; j <= G.vex; j++)
        { // 初始化
            G.arcs[i][j].adj = INTSIZE;
        }
    }
    while (cin >> v1 >> v2 >> info)
    {
        j = locatevex(G, v1);
        k = locatevex(G, v2);
        G.arcs[j][k].adj = info;
        G.arcs[k][j].adj = info;
    }
}
int P[Max_size][Max_size][Max_size], D[Max_size][Max_size];
// P[v][w][u]为ture,则u是从v到w当前最短路径上的顶点
// D[v][w]为带权长度
void serchFOLYD(MG G)
{
    int v, w, u; // v弧头结点下标 w弧尾 u是从v到w最短路径上顶点
    for (v = 1; v <= G.vex; v++)
    {
        for (w = 1; w <= G.vex; w++)
        { // 初始化
            D[v][w] = G.arcs[v][w].adj;
            for (u = 1; u <= G.vex; u++)
                P[v][w][u] = 0;
            if (D[v][w] < INTSIZE)
            { // 初始化标记(从v到w有直接路径)
                P[v][w][u] = 1;
                P[v][w][w] = 1; // w必然是从v到w上的顶点
            }
        }
    }
    for (u = 1; u <= G.vex; u++)
    { // 找到有途径结点更短路径并更新
        for (v = 1; v <= G.vex; v++)
        {
            for (w = 1; w <= G.vex; w++)
            {
                if (D[v][u] + D[u][w] < D[v][w])
                {                                // 途径u后路径更短
                    D[v][w] = D[v][u] + D[u][w]; // 更新
                    for (int i = 1; i <= G.vex; i++)
                    { // 对从v到w上途径结点更新为v到u和u到v有一条路为真就可以
                        P[v][w][i] = P[v][u][i] || P[u][w][i];
                    }
                }
            }
        }
    }
    int arr[Max_size];
    for (int i = 1; i <= G.vex; i++)
    {//找到从v到其他各个村庄的最远路径记录到arr
        arr[i] = D[i][1];
        for (int j = 2; j <= G.vex; j++)
        {
            if (arr[i] < D[i][j])
            {
                arr[i] = D[i][j];
            }
        }
    }
    int min = arr[1], k, cnt = 1;//cnt为记录下标
    for (k = 2; k <= G.vex; k++)
    {//在最远路径中找到最短路径的下标就是要建医院的村庄
        if (min > arr[k])
        {
            cnt = k;
            min = arr[k];
        }
    }
    cout << G.vexs[cnt] << "\n";
}

int main()
{
    MG G;
    creatMG(G);
    serchFOLYD(G);
    return 0;
}

 

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值