洛谷P4779单源最短路(标准版)——(dijkstra + 线段树优化)

今天,一个小学弟问了这个最短路的问题,最开始他问了个板子题P3771

题目背景

本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步 P4779

题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入输出格式

输入格式:

第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。

接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。

输出格式:

一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)

输入:

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

输出:

0 2 4 3

显然这就是一个dijkstra的板子题,直接写就ok了

#include<bits/stdc++.h>
const int N = 1e5 + 7;
const int M = 5e6 + 7;
const int inf = 2147483647;
using namespace std;
struct graph{
    int d,b;
};
vector<graph> w[N];
int dis[N],f[N],minn = inf;
int n,m,k;
void set_graph(int x,int y,int l)
{
    graph res;
    res.d = y;
    res.b = l;
    w[x].push_back(res);
}
void dij()
{
    f[k] = 1;
    for(int i = 1;i <= n;++i) dis[i] = inf;
    for(int i = 0;i < w[k].size();++i)
        dis[w[k][i].d]=min(w[k][i].b,dis[w[k][i].d]);
    dis[k] = 0;
    for(int i = 1;i < n;++i){
        minn = inf;
        int cnt = 0;
        for(int j = 1;j <= n;++j)
         if(f[j] == 0 && dis[j] < minn){
            minn = dis[j];
            cnt = j;
         }
        f[cnt] = 1;
        if(!cnt)    break;
        for(int j = 0;j < w[cnt].size();++j){
            if(w[cnt][j].b + dis[cnt] < dis[w[cnt][j].d])
              dis[w[cnt][j].d] = w[cnt][j].b+dis[cnt];
        }
    }

}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1;i <= m;++i){
        int x,y,l;
        scanf("%d%d%d",&x,&y,&l);
        set_graph(x,y,l);
    }
    dij();
    printf("%d",dis[1]);
    for(int i = 2;i <= n;++i)
        printf(" %d",dis[i]);
    printf("\n");
    return 0;
}

然后,这个可爱的(恶魔的)小学弟问了我这个数学选手,升级版。。。

数据变成了

1<=N<=1000000;

1<=M<=200000 ;

1≤ui,vi,S≤N ;

0≤wi≤109 ,

0≤∑wi​≤109 。

这个就很爆炸了,当然啦,隔壁一大佬说不就是一个堆排序吗,可惜,并不会用堆。。。

然后,在某个不经意间,看到了一个天才的博文,他说可以用线段树优化dijkstra!!!按照他的方法试了一波,我的老天,这都行!!!附上AC代码。

线段树瞎搞版:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 7;
const int M = 5e5 + 7;
const int inf = 0x7fffffff;
const int imf = 0x3f3f3f3f;
int n,m,k;
inline int read() {
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9'){
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x;
}
struct graph{
    int v,next,w;
}edge[M];
int num = 0,head[N];
void set_graph(int a,int b,int c)
{
    edge[++num].v = b;
    edge[num].w = c;
    edge[num].next = head[a];
    head[a] = num;
}
int dis[N],ans[N],s,t;
int tree[N << 2],leaf;
int check(int i,int j)
{
    return dis[i]<dis[j]?i:j;
 }
inline void build()
{
    memset(dis,imf,sizeof dis);
    for(leaf = 1;leaf <= n;leaf <<= 1) ;
    leaf--;
    for(int i = 1;i <= n;++i) tree[leaf + i] = i;
}
void modify(int x,int y) {
    dis[x] = y;
    x += leaf;
    x >>= 1;
    while(x){
        tree[x] = check(tree[x << 1],tree[x << 1|1]);
        x >>= 1;
    }
}
void dij() {
    build();
    dis[k] = 0;
    int u = k;
    for(int i = 1;i <= n;++i) {
        ans[u] = dis[u];
        int disu = dis[u];
        modify(u,inf);
        for(int j = head[u];j;j = edge[j].next){
            int v = edge[j].v;
            if(dis[v] < inf && dis[v] > disu + edge[j].w)
                modify(v,disu + edge[j].w);
        }
        u = tree[1];
    }
}
int main() {
    n = read(),m = read(),k = read();
    for(int i = 1;i <= m;++i) {
        int a = read(),b = read(),c = read();
        set_graph(a,b,c);
    }
    dij();
    for(int i = 1;i <= n;++i) {
        if(dis[i] == imf) ans[i] = inf;
        printf("%d",ans[i]);
        printf(i == n ? "\n" : " ");
    }
    return 0;
}

隔壁大佬正解版:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int maxn=1e5+10;
const int inf=2147483647;

int head[maxn],dis[maxn],cnt,n;

struct Edge
{
    int nex,to,w;
}edge[20*maxn];

void add(int u,int v,int w)
{
    edge[++cnt].nex=head[u];
    edge[cnt].w=w;
    edge[cnt].to=v;
    head[u]=cnt;
}

struct node
{
    int u,dis;
    node(){}
    node(int a,int b):u(a),dis(b){}
    bool operator <(const node &no) const
    {
        return dis>no.dis;
    }
};

void dijkstra(int s)
{
    for(int i=1;i<=n;i++) dis[i]=inf;
    dis[s]=0;
    priority_queue<node> que;
    node st(s,0);
    que.push(st);
    while(!que.empty())
    {
        node f=que.top();
        que.pop();
        int u=f.u,d=f.dis;
        if(d!=dis[u]) continue;
        for(int i=head[u];~i;i=edge[i].nex)
        {
            int v=edge[i].to,w=edge[i].w;
            if(dis[u]+w<dis[v])
            {
                dis[v]=dis[u]+w;
                node tmp(v,dis[v]);
                que.push(tmp);
            }
        }
    }
}

int main()
{
    int m,s,u,v,w;
    scanf("%d%d%d",&n,&m,&s);
    memset(head,0xff,sizeof(head));
    cnt=0;
    while(m--)
    {
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    dijkstra(s);
    for(int i=1;i<=n;i++)
    {
        if(i!=1) printf(" ");
        printf("%d",dis[i]);
    }
    printf("\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41791981/article/details/81202051
今日推荐