hdoj-2544 最短路【最短路径--dijkstra&&spfa&&floyd】

题目http://acm.hdu.edu.cn/showproblem.php?pid=2544

模板题三种解题方法

dijkstra:

#include<cstdio>
#include<cstring>//memset
#include<algorithm>//min
#define INF 0x3f3f3f3f
#define maxn 110
using namespace std;//algorithm
int n,m,map[maxn][maxn],dis[maxn];//map[][]两点之间的距离  dis[]起始点(源点)到当前点的距离 
bool visit[maxn];//判断该点是否被访问 

void dijkstra(int s)
{
	int next;//下一个进入(最短距离) V集合的点 
	memset(visit,0,sizeof(visit));// 一开始 V集合中无任何元素 
//	memset(map,INF,sizeof(map));
	for(int i=1;i<=n;i++)//dis初始化  起始点(源点)到当前点的距离 
		dis[i]=map[s][i];
	visit[s]=true;//将源点放入集合V 
	dis[s]=0;//源点到源点的距离为0 
	for(int i=1;i<n;i++)//已经把U集合中的一个点存入V集合 最多进行n-1次寻找最小值 
	{
		int temp=INF;// 一开始默认两点之间的距离为INF 
		for(int u=1;u<=n;u++)
		{
			if(!visit[u]&&dis[u]<temp)//找最小值(该点不在V集合 并且 该点到源点的距离小于 当前值 ) 
			{
				temp=dis[u];
				next=u;
			}
		}
		visit[next]=true;//将离源点最近的点存入V集合 
		for(int u=1;u<=n;u++)//松弛 
		{
			if(!visit[u])
				dis[u]=min(dis[u],dis[next]+map[next][u]);
		}
	}
}

int main()
{
	int a,b,c;
	while(scanf("%d%d",&n,&m),n,m)
	{
		memset(map,INF,sizeof(map));// 不能在dijkstra()中初始化  对map[][]赋值前初始化 
		while(m--)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(map[a][b]>c)//避免重复   上面初始化为INF map仍为INF表示未走过这条路   
				map[a][b]=map[b][a]=c;
		}
		dijkstra(1);
		printf("%d\n",dis[n]);
	}
	return 0;
}

 

spfa:

#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
#define MAXN 100+10//点数 
#define MAXM 20000+10//边数 
using namespace std;
int n,m,top,vis[MAXN],dis[MAXN],visit[MAXN],head[MAXN];

struct node {
	int from,to,val,next;
};
node edge[MAXM];

void init()//初始化邻接表 
{
	top=0;//建表从零开始
	memset(head,-1,sizeof(head));
}

void add(int u,int v,int w)//建立邻接表
{
	edge[top].from=u;
	edge[top].to=v;
	edge[top].val=w;
	edge[top].next=head[u];
	head[u]=top++;
}


void spfa(int s)//s为源点
{
	queue<int>q;//存储每次入队的点
	memset(vis,0,sizeof(vis));
	memset(dis,INF,sizeof(dis));//存储源点 到这个点的最短路
	vis[s]=1;//表示这个点是否在队列里面
	dis[s]=0;
	q.push(s);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;//该点之后还可能进入队列    消除标记  
		for(int i=head[u];i!=-1;i=edge[i].next)//遍历以u为起点的 所有边
		{
			int v=edge[i].to;
			if(dis[v]>dis[u]+edge[i].val)
			{
				dis[v]=dis[u]+edge[i].val;\
				if(!vis[v])
				{
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
	printf("%d\n",dis[n]);
}

void getmap()
{
	while(m--)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		add(a,b,c);
		add(b,a,c);//无向图  既可由a->b,也可由b->a; 
	}
	
}

int main()
{
	while(scanf("%d%d",&n,&m),n|m)//n|m位运算符  n==0&&m==0时输入结束 
	{
		init();
		getmap();
		spfa(1);
	
	}
	return 0;
}

floyd:

#include<stdio.h>
#define INF 0x3f3f3f3f
int n,m,path[110][110];

void init()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i==j)
                path[i][j]=0;
            else path[i][j]=INF;
        }
}

void floyd()
{
    int i,j,k;
    for(k=1;k<=n;k++)//K是穷举i,j的断点  必须是最外层表示断点 
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                if(path[i][j]>path[i][k]+path[k][j])
                    path[i][j]=path[i][k]+path[k][j];
            }
}

void getmap()
{
    int a,b,c;
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&c);
        if(path[a][b]>c)//防止重复  一开始初始化为INF 若已经选过 则不满足if 
            path[a][b]=path[b][a]=c;
    }
}

int main()
{
    while(scanf("%d%d",&n,&m),n|m)
    {
        init();
        getmap();
        floyd();
        printf("%d\n",path[1][n]);
    }
    return 0;
}

 

搜索

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_29606781/article/details/47750217
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞