zoukankan      html  css  js  c++  java
  • Dijkstra的堆优化

    先附上一个例题:P3371 【模板】单源最短路径

    一眼扫去,最短路。。。

    spfa可行,但是今天的主题是Dijkstra:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 10010
    #define MAXM 500010
    #define MAX 999999999
    using namespace std;
    int n,m,s,c=1;
    int head[MAXN],path[MAXN];
    bool vis[MAXN];
    struct node{
    	int next,to,w;
    }a[MAXM<<1];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add(int u,int v,int w){
    	a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    }
    void dijkstra(){
    	for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}
    	path[s]=0;
    	for(int i=1,k,v;i<=n;i++){
    		k=-1;
    		for(int j=1;j<=n;j++)if(!vis[j]&&(k==-1||path[k]>path[j]))k=j;
    		if(k==-1)break;
    		vis[k]=true;
    		for(int j=head[k];j;j=a[j].next){
    			v=a[j].to;
    			if(!vis[v]&&path[v]>path[k]+a[j].w)path[v]=path[k]+a[j].w;
    		}
    	}
    	for(int i=1;i<=n;i++)printf("%d ",path[i]==MAX?2147483647:path[i]);
    	printf("
    ");
    }
    int main(){
    	int u,v,w;
    	n=read();m=read();s=read();
    	for(int i=1;i<=m;i++){
    		u=read();v=read();w=read();
    		add(u,v,w);
    	}
    	dijkstra();
    	return 0;
    }

    然而,遇上某些题,n<=100,000,怎么办?

    比如:P4779 【模板】单源最短路径(标准版)

    这时候,堆优化就出场了。


    堆优化:

    堆优化,即用堆来实现O( log2n )时间内找到到起点最短的未被松弛的点。

    当然,你需要自定义结构体。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define MAXN 10010
    #define MAXM 500010
    #define MAX 999999999
    using namespace std;
    int n,m,s,c=1;
    int head[MAXN],path[MAXN];
    bool vis[MAXN];
    struct node{
    	int next,to,w;
    }a[MAXM];
    struct Point{
    	int x,dis;
    	bool operator <(const Point &p)const{
    		return dis>p.dis;
    	}
    };
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add(int u,int v,int w){
    	a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    }
    void dijkstra(){
    	Point u,v;
    	priority_queue<Point> q;
    	for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}
    	u.x=s;u.dis=path[s]=0;
    	q.push(u);
    	while(!q.empty()){
    		u=q.top();
    		q.pop();
    		if(!vis[u.x]){
    			vis[u.x]=true;
    			for(int i=head[u.x];i;i=a[i].next){
    				v.x=a[i].to;
    				if(!vis[v.x]){
    					path[v.x]=min(path[v.x],path[u.x]+a[i].w);
    					v.dis=u.dis+a[i].w;
    					q.push(v);
    				}
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)printf("%d ",path[i]==MAX?2147483647:path[i]);
    	printf("
    ");
    }
    int main(){
    	int u,v,w;
    	n=read();m=read();s=read();
    	for(int i=1;i<=m;i++){
    		u=read();v=read();w=read();
    		add(u,v,w);
    	}
    	dijkstra();
    	return 0;
    }
    

    不得不说,这玩意效率虽然没有spfa+SLF高,但是遇上了这题,你也是无可奈何地用它:

    P4768 [NOI2018]归程


    后记:

    附上洛谷上的两次提交:(P3371)

    朴素Dijkstra:Accepted  100

     1036ms /  7.77MB 
    代码:1.11KB C++

    Dijkstra+堆优化:Accepted  100

    348ms /  9.49MB 
    代码:1.3KB C++

    明显快了不少。

    不过出题人没事干也不会卡你的spfa,至少在NOIP这种考试中。。。

  • 相关阅读:
    完了!生产事故!几百万消息在消息队列里积压了几个小时!
    crontab详解
    系统架构中为什么要引入消息中间件
    Linux常用命令
    什么是JWT(JSON WEB TOKEN)
    API接口安全性设计
    MySQLDump在使用之前一定要想到的事情
    api接口安全以及https
    shell study
    linux中注册系统服务—service命令的原理通俗
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9357584.html
Copyright © 2011-2022 走看看