1937. 导游

本文深入讲解了Dijkstra算法的两种实现方式:邻接矩阵和邻接表,并通过具体代码示例详细介绍了如何利用这两种方式来解决最短路径问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一看就是dijkstra算法的变形了。
但是还是要强调的是:
1)用邻接矩阵来表达图的时候,初始化,选择,更改的目的点都是i或者j,循环是对所有的顶点循环
2)用邻接表来表达图的时候,初始化,更改的时候是对目的链来操作,操作点位v[k][j].end,循环也是对链来循环。这个很容易错,我就把d[v[k][j].end]写成了d[j]或d[v[k][j].cost]
注意在传统的dijkstra中用邻接矩阵来求最短路径的时候还一定要注意松弛操作,初始化。最常用的无非是0x3f3f3f3f了。
而返回一般是遇到目的点就返回!(有待验证)

邻接表来解答

#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 110;
int NumVex,NumEdge;
int vis[maxn];
int dis[maxn];
int start,_end,NumPeople;
struct edge {
    int end,cost;
    edge(int _end=0,int _cost=0):end(_end),cost(_cost){}
};

vector<edge> v[maxn];

int f() {
    for (int i=0;i<v[start].size();i++) {
        dis[v[start][i].end] = v[start][i].cost;
    }

    for (int i=0;i<NumVex-1;i++) {
    int tmp = -1,k; for (int j=1;j<=NumVex;j++) {if(!vis[j]&&tmp<dis[j]) {tmp = dis[j];k = j;}}
        vis[k] = 1;
        if (k== _end) return tmp;

        for (int j=0;j<v[k].size();j++) {
            if(!vis[v[k][j].end]) {
                int t = min(v[k][j].cost,dis[k]);
                dis[v[k][j].end] = max(dis[v[k][j].end],t);
            }
        }
    }
    return dis[_end];
}



int main() {
    int t;
    cin>>t;
    while(t--) {
        cin>>NumVex>>NumEdge;
        for(int i=1;i<=NumVex;i++)  v[i].clear();
        for(int i=1;i<=NumEdge;i++) {
            int a,b,c;
            cin>>a>>b>>c;
            v[a].push_back(edge(b,c));
            v[b].push_back(edge(a,c));
        }
        memset(vis,0,sizeof(vis)); memset(dis,-1,sizeof(dis));
        cin>>start>>_end>>NumPeople;
        dis[start] = 0; vis[start] = 1;
        int ans = f() - 1;
        if(NumPeople%ans==0) cout<<NumPeople/ans<<endl;
        else cout<<NumPeople/ans+1<<endl;
    }
}

邻接矩阵来解答

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 200;
const int INF = 0x3f3f3f3f;
int map[maxn][maxn];
int vis[maxn],dis[maxn];
int nv,ne;
struct edge{
    int AdjV;
    int distance;
};

int f(int st,int ed) {
    for (int i=1;i<=nv;i++) {
        vis[i]=0;
        dis[i]=-1;
    } 
    vis[st] = 1; dis[st]=0;
    for(int i=1;i<=nv;i++) {
        if(map[st][i]!=0) {
            dis[i] = map[st][i];
        }
    }

    for(int i=0;i<nv-1;i++) {
        int tmp=-1,k=st;
        for (int j=1;j<=nv;j++) {
            if(!vis[j]&&tmp<dis[j]) {
                tmp = dis[j]; k = j;
            }
        }
        //if (tmp==-1) return dis[ed];
        vis[k] = 1;
        for (int j=1;j<=nv&&k!=st;j++) {
            if(!vis[j]&&dis[j]<min(map[k][j],dis[k])) {
                 dis[j] = min(map[k][j],dis[k]);
            } 
        }
    }
    return dis[ed];
    //else return -1; 
}




int main() {
    int t;
    cin>>t; 
    while(t--) {
     cin>>nv>>ne;
      for (int i=1;i<=nv;i++) 
       for (int j=1;j<=nv;j++) map[i][j]=0;  //这里也也很重要!  
        for (int i=0;i<ne;i++) {
            int a1,a2,a3;
            cin>>a1>>a2>>a3;
                map[a1][a2] = a3;
                map[a2][a1] = a3;
        }
        int st,ed,N;
        cin>>st>>ed>>N;
        int ans = f(st,ed);
        int tmp = N/(ans-1);
        if(tmp*(ans-1)==N) cout<<tmp<<endl;
        else cout<<tmp+1<<endl; 
//      cout<<ans<<endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值