vector存图解决最短路(带堆优化)

21 篇文章 0 订阅
7 篇文章 0 订阅

小明的爸爸突然想抽烟,于是派小明去买烟。现在小明想要寻找最短的从商店到家的路线,你可以帮助他吗?
Input

输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示有几个路口,标号为1的路口是商店所在地,标号为N的路口是家所在地,M则表示有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,小明需要C分钟的时间走过这条路。
输入保证至少存在1条商店到家的路线。

 对于每组输入,输出一行,表示小明从商店走到家的最短时间

Output 

2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0

Sample Output 

3
2

 

裸的最短问题,dijkstra和Floyd都可以做,这里N 的范围比较小,但是如果N非常大但是M很小的话,dijkstra的邻接矩阵存储图会爆内存,下面用邻接表来实现存图

这里用vector来实现邻接表的操作

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
#define N 110
#define INF 0x3f3f3f3f
using namespace std;
 
int n,m,a,b,c,vis[N],dis[N],Min;
 
struct node
{
    int d,w;
};//定义一个结构体来存储每个入度点以及对应边的权值
//比如边u->v,权值为w,node结构体存储的就是v以及w。
 
vector<node>v[N];
 
void dijkstra();
 
int main()
{
    //对于N非常大但是M很小的这种稀疏图来说,用邻接矩阵N*N是存不下的。邻接矩阵是将所有的点都存储下来了,然而
    //对于稀疏图来说,有很多点是没有用到的,把这些点也存储下来的话就会很浪费空间。可以用邻接表来存储,这里借助vector来实现邻接表的操作。
    //用邻接表存储时候,只存储有用的点,对于没有用的点不存储,实现空间的优化。
    while(cin>>n>>m,n!=0||m!=0)
    {
        for(int i=0; i<=n; i++)
            v[i].clear();//将vecort数组清空
        for(int i=1; i<=m; i++) //用vector存储邻接表
        {
            node nd;
            scanf("%d%d%d",&a,&b,&c);
            nd.d=b,nd.w=c;//将入度的点和权值赋值给结构体
            v[a].push_back(nd);//将每一个从a出发能直接到达的点都压到下标为a的vector数组中,以后遍历从a能到达的点就可以直接遍历v[a]
            nd.d=a,nd.w=c;//无向图的双向存边
            v[b].push_back(nd);
        }
        dijkstra();
        printf("%d\n",dis[n]);
    }
    return 0;
}
 
void dijkstra()
{
    //初始位置从顶点1开始。
    memset(vis,0,sizeof(vis));//初始化标记数组
    for(int i=0; i<=n; i++)
        dis[i]=INF;//先将dis初始化为无穷大,下面更新dis的初始值。
    int len=v[1].size();//找到从起始位置能到达的点有几个,v[1]的大小就是能到达的点的个数
    for(int i=0; i<len; i++) //循环遍历每个点然后更新dis初始值
    {
        if(dis[v[1][i].d]>v[1][i].w)//v[1][i].d代表从1出发能到达的顶点中第i个点的值,
            //dis数组记录从1出发到该顶点的距离,v[1][i].w代表从1出发能到达的顶点中,到达第i个顶点的边的权值
            dis[v[1][i].d]=v[1][i].w;//更新dis数组,这里更新的时候包括了对重边的更新
    }
    vis[1]=1;
    int k;
    for(int i=1; i<n; i++)
    {
        Min=INF;
        for(int j=1; j<=n; j++) //dijkstra找最近的点
        {
            if(vis[j]==0&&dis[j]<Min)
            {
                Min=dis[j];
                k=j;
            }
        }
        vis[k]=1;//k为找到的点
        len=v[k].size();//从k出发能到达的点的个数
        for(int j=0; j<len; j++) //循环遍历k能到达的点(假设为vi),比较从源点到达q的距离,和从源点出发借助k这个点中转再到达q的距离,然后更新dis数组
        {
            int vi=v[k][j].d;//v[k][j].d代表从k出发能到达的顶点中第j个顶点的值
            if(vis[vi]==0&&dis[vi]>dis[k]+v[k][j].w)//借助k这个点能进行松弛操作的话,更新
                dis[vi]=dis[k]+v[k][j].w;
        }
    }
}
 

堆优化

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<queue>
#include <vector>
#include <map>
int s,t;
int n,m;
using namespace std;
const int INF=99999999;
struct Node{
    int to;
    int w;
};
struct Node temp;
vector<Node> v[1002];
typedef pair<int, int> P;
int dis[1002];

void Dijkstra(){
    for(int i=1;i<=n;i++)
        dis[i]=INF;
    priority_queue<P,vector<P>,greater<P> >que;
    que.push(P(0,1));
    dis[1]=0;
    while(!que.empty()){
        P p=que.top();que.pop();
        if(dis[p.second]<p.first)
            continue;
        for(int i=0;i<v[p.second].size();i++){
            if(dis[v[p.second][i].to]>dis[p.second]+v[p.second][i].w){
                dis[v[p.second][i].to]=dis[p.second]+v[p.second][i].w;
                que.push(P(dis[v[p.second][i].to],v[p.second][i].to));
            }
        }
    }
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        v[i].clear();
    for(int i=1;i<=m;i++){
            cin>>s>>temp.to>>temp.w;
            v[s].push_back(temp);
    }
    Dijkstra();
    cout<<dis[6];
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值