非负权单源最短路

Description

 

给一个 nn 个点 mm 条边的无向图,求 ss 到 tt 的最短路。

Input

 

第一行四个由空格隔开的整数 nn、mm、ss、tt 。

之后 mm 行,每行三个正整数 u_iui​、v_ivi​、w_iwi​ ,表示一条从 u_iui​ 到 v_ivi​ 长度为 w_iwi​ 的边。

保证:

1 \leq n \leq 25001≤n≤2500 ,1 \leq m \leq 62001≤m≤6200 ,1 \leq u_i, v_i \leq n1≤ui​,vi​≤n ,1 \leq w_i \leq 10 ^ 91≤wi​≤109。

Output

 

一个整数表示从 ss 到 tt 的最短路的长度,数据保证 ss 与 tt 是连通的。

Sample Input 1 

7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

Sample Output 1

7

Source

LOJ

https://oi-wiki.org/graph/shortest-path/

上面是算法讲解;

如果数据再大一点。

用Dijkstra

需要优先队列。

不会,学一波

https://oi-wiki.org/ds/stl/priority_queue/

这里有讲解。

也可以去看看别人的博客;

#include <iostream>
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define maxn 2510
bool inqueen[3001];
struct Edge{
    int v,cost;
};
ll dis[3001],inf=ll(1e18);
vector<Edge> edge[maxn];
int main()
{
    int n,m,s,t,u,v,w;
    scanf("%d %d %d %d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&u,&v,&w);
        edge[u].push_back({v,w});
        edge[v].push_back({u,w});
    }
    queue<int>Q;
    for(int i=1;i<=n;i++)
    {
        dis[i]=inf;
    }
    memset(inqueen,false,sizeof(inqueen));
    dis[s]=0;
    Q.push(s);
    inqueen[s]=true;
    while(!Q.empty()){
        int b=Q.front();
        Q.pop();
        //printf("%d\n",b);
        inqueen[b]=false;
        int size=int(edge[b].size());
        for(int i=0;i<size;i++)
        {
            int v=edge[b][i].v,cost=edge[b][i].cost;
            if(dis[v]>dis[b]+cost){
                dis[v]=dis[b]+cost;
                if(!inqueen[v]){
                    Q.push(v);
                    inqueen[v]=true;
                }
            }
        }
    }
    printf("%lld\n",dis[t]);
    return 0;
}
#include <iostream>
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
bool inqueen[2510];
ll dis[2510],inf=ll(1e18);
int a[2510][2510];
int main()
{
    int n,m,s,t,u,v,w;
    scanf("%d %d %d %d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&u,&v,&w);
        a[u][v]=w;
        a[v][u]=w;
    }
    for(int i=1;i<=n;i++)
    {
        dis[i]=inf;
    }
    memset(inqueen,false,sizeof(inqueen));
    dis[s]=0;
    queue<int>Q;
    Q.push(s);
    inqueen[s]=true;
    while(!Q.empty()){
        int b=Q.front();
        Q.pop();
        //printf("%d\n",b);
        inqueen[b]=false;
        for(int i=1;i<=n;i++)
        {
            if(a[b][i]>0&&dis[i]>dis[b]+a[b][i])
            {
                dis[i]=dis[b]+a[b][i];
                if(!inqueen[i])
                {
                    Q.push(i);
                    inqueen[i]=true;
                }
            }
        }
    }
    printf("%lld\n",dis[t]);
    return 0;
}

一种是邻接矩阵,一种是邻接表

下面是Dijkstra;

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n,m,s,t;
typedef long long ll;
const int N =100001;
ll dist[N],inf=ll(1e18);
bool inque[N];
struct edge
{
    int v;
    int time;
};
struct youxian{
    int index;
    ll dist;
    bool operator<(const youxian &tmp)
    const {
        return dist>tmp.dist;
    }
};
vector<edge>e[N];
ll fun()
{
    int i;
    for(i=1;i<=n;i++)
    {
        dist[i]=inf;
        inque[i]=false;
    }
    dist[s]=0;
    priority_queue<youxian>Q;
    Q.push({s,0});
    while(!Q.empty()){
        int u=Q.top().index;
        Q.pop();
        if(inque[u]) continue;
        inque[u]=true;
        int size=int (e[u].size());
        for(i=0;i<size;i++){
            int v=e[u][i].v,time=e[u][i].time;
            if(dist[v]>dist[u]+time){
                dist[v]=dist[u]+time;
                Q.push({v,dist[v]});
            }
        }
    }
    return dist[t];
}
int main()
{
    int u,v,w;
    scanf("%d %d %d %d",&n,&m,&s,&t);
    for(int i=0;i<m;i++){
        scanf("%d %d %d",&u,&v,&w);
        e[u].push_back({v,w});
        e[v].push_back({u,w});
    }
    printf("%lld\n",fun());
    return 0;
}

 

posted on 2019-01-17 20:49  湫叶  阅读(111)  评论(0编辑  收藏  举报

导航