最短路——dijkstra

朴素Dijstra单源最短路算法:

#include<cstdio>
#include<iostream>
using namespace std;
const int inf=2e9;
int map[105][105],dist[105],m,n,x,y;     //s[i]数组保存到i的最短路长度
bool vis[105];

void input(){
	int p,q,i,j,t;
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++){
		scanf("%d%d%d",&p,&q,&t);
		map[p][q]=t;
	}
	for(i=1;i<=n;i++)
 		for(j=1;j<=n;j++)
 			if(!map[i][j])map[i][j]=inf;  //初始化
 	scanf("%d%d",&x,&y);
}
void dijkstra(){
	int i,k,j;
	for(i=1;i<=n;i++)dist[i]=map[x][i];
	vis[x]=true;
	do{
		int minn=inf;
		k=0;
		for(i=1;i<=n;i++)     //找到未讨论的最近点
		if(!vis[i]&&dist[i]<minn)
		minn=dist[i],k=i;
		if(k>0){
			vis[k]=true;
			for(i=1;i<=n;i++)
			dist[i]=min(dist[i],dist[k]+map[k][i]);    //更新到i的最短路长度
		}		
	}while(k>0);
	printf("%d",s[y]);
}
int main(){
	input();
	dijkstra();
}



该算法也可以适用于无向图,但要求图中不能有负权。

dijkstra也可以求解次短路,只需要把dist和vis改成二维数组,但是如果有重边,则必须改为用边存图。

代码如下:

void dijkstra(int s)
{
     int i,j,k,t,y,z,minn;
     for(i=1;i<=n;i++){      //初始化
         dis[i][0]=dis[i][1]=inf;      //dis[i][0]表示最短路,dis[i]1]表示次短路。
         vis[i][0]=vis[i][1]=false;
     }
     dis[s][0]=0;
     do{
         k=0; minn=inf;
         for(i=1;i<=n;i++){
             if(!vis[i][0]&&dis[i][0]<minn)   //找到讨论点
                 minn=dis[i][0],k=i,t=0; 
             else if(!vis[i][1]&&dis[i][1]<minn)
                  minn=dis[i][1],k=i,t=1;
         }
         if(k>0){
             vis[k][t]=true;
             j=last[k];
             while(j!=0){
                  y=line[j].end; z=line[j].len;
                  if(minn+z<dis[y][0]) {
                      dis[y][1]=dis[y][0];
                      dis[y][0]=minn+z;
                  }
                  else if((minn+z<dis[y][1])&&(minn+z>dis[y][0]))
				  dis[y][1]=minn+z;
                  j=line[j].next;
             }
         }
     }while(k>0);                
}




使用边存储和优先队列优化的,结构体形式版Dijstra:

#include<cstdio>  
#include<iostream>
#include<cstring>  
#include<queue>  
#include<vector>   
 
#define CLEAR(XXX) memset((XXX),0,sizeof(XXX))
using namespace std; 
 
const int inf=1e9;  
const int maxn=1005,maxm=1005;  
 
int n,m;
  
inline void _read(int &x){  
    char ch=getchar(); bool mark=false;  
    for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;  
    for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';  
    if(mark)x=-x;  
}  
struct Edge{  
    int from,to,w;  
    Edge(int from,int to,int w):from(from),to(to),w(w){}
};
struct node{   //建小根堆用 
	int d,u;
	node (int d,int u):d(d),u(u){}
	bool operator < (const node& a)const {
		return d>a.d;	
	}
};    
struct Dijstra{  
    int  n,m;  
    vector<Edge> edge;  
    int last[maxm],Next[maxm],dist[maxn];   
    bool vis[maxn];  
    
    void init(int n){  
        this->n = n;  
        m=0;  
        CLEAR(last);  CLEAR(Next);  
        edge.clear();  
        edge.push_back(Edge(0,0,0));  
    }  
    void add_edge(int from,int to,int dist){  
        edge.push_back(Edge(from,to,dist));  
        m=edge.size()-1;  
        Next[m]=last[from];  
        last[from]=m;  
    }  
    void solve(int s){  
        int i;  
        priority_queue <node> q; 
        CLEAR(vis);    
        for(i=1;i<=n;i++) dist[i]=inf;  
        dist[s]=0;
        q.push(node(0,s));
		vis[s]=true;    
        while(!q.empty()){ 
            int x=q.top().u; 
            q.pop();  
            for(i=last[x];i;i=Next[i]){ 
                Edge& e=edge[i];   
                if(dist[e.from]+e.w<dist[e.to]){  
                    dist[e.to]=dist[e.from]+e.w;  
                    if(!vis[e.to]){    
                        q.push(node(dist[e.to],e.to)) ;  
                        vis[e.to]=true;  
                    }  
                }   
            }  
        }  
    }   
};   
int main(){  
    Dijstra solver;
	int  i,j,x,y,w;
	_read(n);_read(m);
	solver.init(n);
	for(i=1;i<=m;i++){
		_read(x);_read(y);_read(w);
		solver.add_edge(x,y,w);
	}
	_read(x);_read(y);
	solver.solve(x);
	printf("%d",solver.dist[y]);
	return 0;
}  


    


你可能感兴趣的:(最短路——dijkstra)