杭电oj2544最短路径

先上题目:杭电oj2544最短路径
典型的最短路径题目,有经典的二种算法
迪杰斯特拉算法和弗洛伊德算法,二种算法各有好坏
先上理解:
迪杰斯特拉算法原理:
从起点开始,遍历起点到与其连通的点的最短路径的点,然后解锁该点,将这二点的路径放进距离数组中,将起点标记为已遍历,以后都不会在计算,遍历该点与其连通的点的最短路径的点,一直这样循环操作,直到遍历到终点时退出,此时距离数组中终点数的代表值就是起点到终点的距离。
该算法只能用于带正权的连通图中,有负权就没用了。
利用的就是广搜加贪心的思想。
个人理解,大家结合代码看一下叭

/*迪杰斯特拉算法,适用于正权连通图*/
/*迪杰斯特拉算法:
解决问题:求起点到终点的最短路径,
适用范围:不带环的正权连通图,
算法原理:从起点开始找其相连的点的最短路径,找到这点就将其标记,并算入最短路径中
在通过该点找与其相邻的点中的最短路径,直到找到终点退出循环。*/
#include<stdio.h>
#include<algorithm>
using namespace std;

int n,m;
int Map[105][105];   //邻接矩阵图
int flag[105];            //标记数组
int dis[105];             //各点的距离
int INF = 0x7fffffff;   //无穷大

void Fun()
{
    dis[1] = 0;    //关键一步,不然接下来的判断全有问题
    int i,j,pos,t;
    for(i = 1;i <= n;i++)   /*实现方式,通过起点寻找其与之相邻权值最小的点,找到该点后起点标记不在查找,
                                       在通过该点找下一个相连的点的权值最小的点,中间累计将权值加起来,最后当找的点为终点时,寻找结束
                                       输出答案*/
    {
            t = INF;
            for(j = 1;j <= n;j++)  /*该步骤是找前面的点到后面是权值最小的那个点,该点是由下面那个判断找到的,而一开始的条件是初始化时给的
                                             即起点到起点的距离为0*/
            {
                if(flag[j] == 0)
                {
                    if(dis[j] < t)
                    {
                        t = dis[j];
                        pos = j;
                    }
                }
            }
            flag[pos] = 1;
            if(pos == n)break;   //到终点了最短路径已经找到,退出函数,或者没有起点到终点是路
            for(j = 1;j <= n; j++)
            {
                if(flag[j] == 0)    //寻找当前点到相邻点权值最小的点,并将其路径累加
                {
                    if(Map[pos][j] !=INF && dis[pos]+Map[pos][j] < dis[j] )
                        dis[j] = dis[pos]+Map[pos][j];
                }
            }
    }
}

int main()
{
    int x,y,v,i,j;
    while(scanf("%d %d",&n,&m)&&(n||m))
    {
        for(i=1;i<=n;i++)
        {
            flag[i] = 0;            //初始化各点统统标记为未探索
            dis[i] = INF;         //初始化各点的距离统统为无穷大
            for(j=1;j<=n;j++)
                Map[i][j] = INF;  //矩阵图也标记为无穷大
        }
        for(i = 1;i<=m;i++)
        {
            scanf("%d %d %d",&x,&y,&v);    //输入对应关系到矩阵图中
            if(x != y &&Map[x][y] > v)
                Map[x][y] = Map[y][x] =v;
        }
        Fun();
        printf("%d\n",dis[n]);
    }
    return 0;
}

*/

接下来就是弗洛伊德算法啦,比较其迪杰斯特拉算法简单易懂而且代码简单,可以用于带负权的连通图中,而且可以计算任意二点间的距离,唯一的缺点可能就是时间复杂度太高了,有0(n^3)额。
弗洛伊德算法:
实现原理,初始化各点间的距离为INF,然后通过题目给定条件赋予各点之间的权值,初始化自己到自己的距离为0。
然后接下来的操作直接看老师的讲解叭(主要是我还不太会*^*):弗洛伊德算法

/*弗洛伊德算法可以求出任意二点间的最短路径,而且代码简单易懂,
缺点就是时间复杂度为n^3,太大了,实测比迪杰斯特拉算法慢4倍*/
#include<iostream>
using namespace std;
#define INF 1000005

int a[1005][1005];

int main()
{
	int n,m;
	int b,c,d;
	int t;
	while(cin>>n>>m&&(m||n))
	{
		for(int i=1;i<=n;i++)
            {
			for(int j=1;j<=n;j++)
			{
				a[i][j]=INF;
			}
		}

	    for(int i=1;i<=m;i++)
	    {
		    cin>>b>>c>>d;
	    	a[b][c] = a[c][b] = d;
	    }

	    for(int i=1; i<=n; i++)
        a[i][i]=0;                         //自己到自己的距离为0

    	for(int k = 1; k <= n; k++)       //将每个点依次加入,看加入该点后以下二点的距离会不会改变
        for(int i = 1; i <= n; i++)          //计算任意二点间的距离
            for(int j = 1; j <= n; j++)
                if(a[i][j] > a[i][k]+a[k][j])
                    a[i][j] = a[i][k]+a[k][j];
                    cout<<a[1][n]<<endl;   //最后可求出任意二点间的距离
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子味汽水ღ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值