dijkstra板子

描述

给定带权无向图G(V,E)和源点s/终点t,求一条 s->t 的最短路径。假设读入边的列表是有(字典)序的(既邻接表就是有序的)。

输入

第一行包含4个整数N、M、s、t,表示该图共有N个结点和M条无向边。(N <= 5000,M <= 200000)。起点为s,终点为t
接下来M行,每行包含3个整数{u,v,w},表示有一条权值为w的无向边连接结点u、v

输出

输出最短路的长度
若无法到达,输出"No path"

样例输入

4 5 1 4
1 2 2
1 3 1
1 4 5
2 4 3
3 4 5

样例输出

5
#include<cstdio>
#include<cstring>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
struct Node
{
    int var,next,val;
} edge[100000005];
int head[100005],tot,dis[100005],N,M;
bool vis[100005];
priority_queue<PII> Q;
void add(int a, int b, int c)
{
    edge[++tot].var = b;
    edge[tot].val = c;
    edge[tot].next = head[a];
    head[a] = tot;
}
void init()//多组输入调用
{
    tot=0;
    memset(head,0,sizeof(head));
}
void dijkstra(int s)
{
    memset(dis,0x3f,sizeof(dis));
    //memset(vis,0,sizeof(vis));
    //while(Q.size()) Q.pop();
    dis[s] = 0;
    Q.push(make_pair(0,s));
    while(!Q.empty())
    {
        int x=Q.top().second;
        Q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x]; i; i=edge[i].next)
        {
            int y=edge[i].var;
            if(dis[x]+edge[i].val<dis[y])
            {
                dis[y]=dis[x]+edge[i].val;
                if(!vis[y])
                Q.push(make_pair(-dis[y],y));
            }
        }

    }
}
int main()
{
    int S,T;
    scanf("%d %d %d %d",&N,&M,&S,&T);
    while(M--)
    {
        int x,y,z;
        scanf("%d %d %d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    dijkstra(S);
    if(dis[T]<0x3f3f)
    printf("%d\n",dis[T]);
    else
        printf("No path\n");
}

点我

用map容器把字符串改换成对应的int型数字, 另外就是要记录下一共出现了多少不同的字符串

#include<iostream>
#include<stdio.h>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int n,mm,ans;
char s1[105],s2[105];
bool vis[2000];
int tu[105][105];
int num[105];
int dijkstra(int a,int b)  //找两点间的最短路
{
    memset(vis,0,sizeof(vis));
    for(int i=a;i<=b;i++)
        num[i]=tu[a][i];
    num[a]=0;
    for(int i=a;i<=b;i++)
    {
        int min=INF,u=-1;
        for(int j=a;j<=b;j++)
        {
            if(!vis[j]&&num[j]<min)
            {
                min=num[j];
                u=j;
            }
        }
        if(min==INF) break;
        vis[u]=1;
        for(int k=a;k<=b;k++)
            if(!vis[k]&&num[k]>num[u]+tu[k][u])
                num[k]=num[u]+tu[k][u];

    }
    return num[2];
}
int main()
{
    map<string,int> m;  //定义一个map函数 名为mat;
    ios::sync_with_stdio(false);
    while(cin>>n&&n>=0)
    {
        m.clear();  //清空mat;
        memset(tu,INF,sizeof(tu));
        cin>>s1>>s2;
        int flag=0;
        if(!strcmp(s1,s2))     //判断起点和终点是否相等;
            flag=1;
        m[s1]=1;     //s1用数字1表示;  字符数字化;
        m[s2]=2;
        ans=2;    //从2开始代替标识;
        for(int i=0;i<n;++i)
        {
            cin>>s1>>s2>>mm;
            if(!m[s1])    //判断是否与起点相同;不同加以1;  相等时mat[s1]=1;不等=0;
                m[s1]=++ans;
            if(!m[s2])   //判断是否与终点相同;不同加以1;
                m[s2]=++ans;
            if(mm<tu[m[s1]][m[s2]])  //存到数组里,用数组表示;
            {
                tu[m[s1]][m[s2]]=mm;
                tu[m[s2]][m[s1]]=mm;
            }

        }
        if(flag)   //如果起点与终点相等,则进入循环
        {
            puts("0");
            continue;
        }
        int t=dijkstra(1,ans);
        if(t==INF)
            puts("-1");
        else
            cout<<t<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值