刷题——最短路径算法!第二篇

本文介绍了两种最短路径算法的应用,C部分讲述了草儿如何利用贝尔曼-福特算法规划旅行的最短时间,D部分则展示了如何在复杂的交通网络中寻找起点到终点的最短距离。这两个问题都通过遍历和更新邻接矩阵来找到最短路径,体现了图论在实际问题中的应用。
摘要由CSDN通过智能技术生成

C - 草儿是个路痴

虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,0),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
Output
输出草儿能去某个喜欢的城市的最短时间。
Sample Input
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10
Sample Output
9
题解
题目意思就是有S个起点,D个终点,求起点到终点所有路径中的最短路。
AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxe = 100100, maxv = 1100;
const int INF = unsigned(-1) >> 1;
int m, s, n;
struct edge
{
    int x, y;
};
edge es[maxe]; //边
struct Graph
{
    int dis;
};
Graph G[maxv][maxv]; //邻接矩阵
struct dist
{
    int dis;
};
dist d[maxv]; //最短路径
void fun(int s)
{
    while (true)
    {
        bool updata = false;
        for (int i = 0; i < m; i++) //遍历所有的边
        {
            edge e = es[i];
            if (d[e.x].dis != INF) //如果遍历过e.x点
            {
                if (d[e.x].dis + G[e.x][e.y].dis < d[e.y].dis) //如果从e.x点走到e.y点的路径 比 其他点走到e.y的路径要短
                {
                    d[e.y].dis = d[e.x].dis + G[e.x][e.y].dis; //更新e.y的路径为更短的
                    updata = true;
                }
            }
            if (d[e.y].dis != INF) //如果遍历过e.y点
            {
                if (d[e.y].dis + G[e.x][e.y].dis < d[e.x].dis) //如果从e.y点走到e.x点的路径 比 其他点走到e.x的路径要短
                {
                    d[e.x].dis = d[e.y].dis + G[e.x][e.y].dis; //更新e.x的路径为更短的
                    updata = true;
                }
            }
        }
        if (updata == false) //如果所有的边都遍历过了,路径信息没有更新过,说明已经遍历完了,结束搜索
            break;
    }
}
int main()
{
    while (scanf("%d%d%d", &m, &s, &n) != EOF)
    {
        int dis;
        for (int i = 1; i < maxv; i++) //初始化邻接矩阵
            for (int j = 1; j < maxv; j++)
                G[i][j].dis = INF;
        for (int i = 0; i < m; i++)
        {
            scanf("%d%d%d", &es[i].x, &es[i].y, &dis);

            if (dis < G[es[i].x][es[i].y].dis) //构建邻接矩阵
                G[es[i].x][es[i].y].dis = G[es[i].y][es[i].x].dis = dis;
        }
        for (int i = 0; i < maxv; i++) //初始化最短距离
            d[i].dis = INF;
        int city[maxv];
        for (int i = 0, x; i < s; i++) //草儿的邻居
        {
            scanf("%d", &x);
            d[x].dis = 0;
        }
        for (int i = 0; i < n; i++) //草儿喜欢的城市
            scanf("%d", city + i);
        int ans = INF;
        fun(0);
        for (int i = 0; i < n; i++)
        {
            ans = min(ans, d[city[i]].dis);
        }
        printf("%d\n", ans);
    }
    return 0;
}

D - 稀的泥和热的油

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
Sample Input
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
Sample Output
2
-1

题解
就一个基本的单源最短路,上Bellman-Ford算法 !
AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxe = 100100, maxv = 1100;
const int INF = unsigned(-1) >> 1;
int n, m, s, t;
struct edge
{
    int x, y;
};
edge es[maxe];
struct Graph
{
    int dis;
};
Graph G[maxv][maxv];
struct dist
{
    int dis;
};
dist d[maxv];
void fun(int s)
{
    for (int i = 0; i < n; i++)
        d[i].dis = INF;
    d[s].dis = 0;
    while (true)
    {
        bool updata = false;
        for (int i = 0; i < m; i++) //遍历所有的边
        {
            edge e = es[i];
            if (d[e.x].dis != INF) //如果遍历过e.x点
            {
                if (d[e.x].dis + G[e.x][e.y].dis < d[e.y].dis) //如果从e.x点走到e.y点的路径 比 其他点走到e.y的路径要短
                {
                    d[e.y].dis = d[e.x].dis + G[e.x][e.y].dis; //更新e.y的路径为更短的
                    updata = true;
                }
            }
            if (d[e.y].dis != INF) //如果遍历过e.y点
            {
                if (d[e.y].dis + G[e.x][e.y].dis < d[e.x].dis) //如果从e.y点走到e.x点的路径 比 其他点走到e.x的路径要短
                {
                    d[e.x].dis = d[e.y].dis + G[e.x][e.y].dis; //更新e.x的路径为更短的
                    updata = true;
                }
            }
        }
        if (updata == false) //如果所有的边都遍历过了,路径信息没有更新过,说明已经遍历完了,结束搜索
            break;
    }
}
int main()
{
    while (scanf("%d%d", &n, &m) != EOF)
    {
        int dis;
        if (n == 0 && m == 0)
            break;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                G[i][j].dis = INF;
        for (int i = 0; i < m; i++)
        {
            scanf("%d%d%d", &es[i].x, &es[i].y, &dis);
            if (dis < G[es[i].x][es[i].y].dis)
                G[es[i].x][es[i].y].dis = G[es[i].y][es[i].x].dis = dis;
        }
        scanf("%d%d", &s, &t);
        fun(s);
        if (d[t].dis == INF)
            puts("-1");
        else
            printf("%d\n", d[t].dis);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值