最短路问题——Dijkstra算法模板

Dijkstra算法简介

Dijkstra算法主要用来解决边权为正时的单源最短路问题(就是从一个源点出发,到所有结点的最短路),同时适用于有向图和无向图

Dijkstra算法思路

Dijkstra算法模板

时间复杂度为O(n^2)

没有堆优化的代码
时间复杂度为O(n^2)

const int INF=1<<30;	
int v[maxn];
int d[maxn];
int w[maxn][maxn];

memset(v,0,sizeof(v));
for(int i=0;i

进行堆优化的代码
时间复杂度为O(mlogn)

struct edge{   //储存边
	int from,to,w;
	edge(int u,int v,int d):from(u),to(v),w(d){}
}
struct node{		//用来结合优先队列使用
	int d,u;
	bool operator < (const node &rhs) const {
		return d>rhs.d;
	}
}
vectoredges;
vectorg[maxn];
int d[maxn];

void addedge(int from ,int to,int wei){   //加边函数,若为无向边,则调用addedge(u,v,w);addedge(v,u,w);各一次
	edges.push_back(edge(from,to,wei));
	m=edges.size();
	g[from].push_back(m-1);
}

void dij(){
	priority_queue q;
	for(int i=0;i<=t;i++) d[i]=INF;
	d[s]=0;
	memset(done,0,sizeof(done));
	q.push((node){0,s});
	while(!q.empty()){
		node x=q.top();q.pop();
		int u=x.u;
		if(done[u]) continue;
		done[u]=1;
		for(int i=head[u];~i;i=nxt[i]){
			if(d[to[i]]>d[u]+dis[i]){  	//松弛操作
				d[to[i]]=d[u]+dis[i];
				q.push((node){d[to[i]],dis[i]});
			}
		}
	}
}

递归打印最短路径

void print(int t){  //s为源点,t为终点	
	printf("%d  ",t);
	if(s==t) return;
	for(int i=0;i

dij算法解决多源多汇问题

题目 HDU - 6166

AC代码

#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=100005;
const long long INF=0x3f3f3f3f3f3f3f3f;
int tot,k;
int head[maxn],done[maxn],a[maxn],mark[maxn];
long long d[maxn];
struct edge{
    int to,next;
    long long dis;
}edges[maxn];
struct node{
    int u;
    long long d;
    bool operator < (const node& rhs) const{
        return d>rhs.d;
    }
};
priority_queueq;
void addedge(int from,int to,long long w){
    edges[tot].to=to;
    edges[tot].dis=w;
    edges[tot].next=head[from];
    head[from]=tot++;
}

long long dij(){
    while(!q.empty()){
        struct node x=q.top();q.pop();
        if(mark[x.u]) return x.d;
        if(done[x.u]) continue;
        done[x.u]=1;
        for(int i=head[x.u];~i;i=edges[i].next){
            if(d[edges[i].to]>d[x.u]+edges[i].dis){
                d[edges[i].to]=d[x.u]+edges[i].dis;
                q.push(node{edges[i].to,d[edges[i].to]});
            }
        }
    }
    return INF;
}

void init(){
    memset(done,0,sizeof(done));
    memset(mark,0,sizeof(mark));
    memset(d,0x3f3f3f3f3f3f3f3f,sizeof(d));
    while(!q.empty()) q.pop();
}

int main(){
    int t,n,m,kase=0;
    int u,v;
    long long w;
    scanf("%d",&t);
    while(t--){
        tot=0;
        memset(head,-1,sizeof(head));
        long long ans=INF;
        scanf("%d%d",&n,&m);
        for(int i=0;i

https://cn.vjudge.net/problem/766699/origin

这道题有多种思路。下面写的思路是设置一个古城中心,各个古城到古城中心设一条长度为x/2的无向边

ac代码

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int t,n,k,m,s;
double X;
const int maxn=1e6;
int done[maxn];
double d[maxn];
struct edge{
    int from,to;
    double dis;
    edge(int u,int v,double d):from(u),to(v),dis(d){}
};
vectores;
vectorg[maxn];
struct node{
    double d;
    int u;
    bool operator <(const struct node & rhs) const{
        return d > rhs.d;
    }
};

void addedge(int u,int v,double d){
    es.push_back(edge(u,v,d));
    es.push_back(edge(v,u,d));
    int m=es.size();
    g[u].push_back(m-2);
    g[v].push_back(m-1);
}

void dij(int s){
    priority_queueq;
    for(int i=0;i<=n;i++) d[i]=0x3f3f3f3f3f3f3f3f;
    d[s]=0;
    memset(done,0,sizeof(done));
    q.push((node){0,s});
    while(!q.empty()){
        node x=q.top();q.pop();
        int u=x.u;
        if(done[u]) continue;
        done[u]=1;
        for(int i=0;id[u]+e.dis){
                d[e.to]=d[u]+e.dis;
                q.push((node){d[e.to],e.to});
            }
        }
    }
}

int main(){
    scanf("%d",&t);
    while(t--){
        int a,b;
        double w;
        scanf("%d%d%lf%d%d",&n,&k,&X,&m,&s);
        for(int i=0;i<=n;i++) g[i].clear();es.clear();
        for(int i=0;i

如有错误,欢迎指出

你可能感兴趣的:(图论算法)