最短路:Dijkstra

最短路:Dijkstra

1算法流程

:我们要维护一个顶点集合C,满足对于所有集合C中的顶点x,我们都已经找到了起点S到x的最短路,此时dist(x)记录的就是我们最终最短路的长度

将C设置为空,经S的距离设置为0,其余顶点设置为无穷大(-1)
在每一轮中,将离起点最近的(dist最小,不能是无穷大)的还不在C中的顶点加入C,用这个点连出去的边通过松弛操作更新dist数组 
当T没有新的点加入,算法结束

2Code:

时间复杂度On2+m)

struct Node{
    int y,v;
    Node(int _y,int _v){ y=_y;v=_v;};
};
vector<Node> edge[N+5];
int n,m,dist[N+5];
bool b[N+5];
int Dijkstra(int s,int ){
    memset(b,fase,sizeof(b));
    memset(dist,-1,sizeof(dist));
    dist[s]=0;
    while(true){
        int x=-1;
        for(int i=1;i<=n;i++){
            if(!b[i]&&dist[i]!=-1)
                if(x==-1||dist[i]<dist[x])
                    x=i;
        }
        if(x==t||x==-1) break;
        b[x]=true;
        for(auto i:edge[x])
            dist[i.y]=min(dist[i.y],dist[x]+i.v);
    }
    return dist[t];
}

3 算法优化:

-我们可以采用一个堆(优先队列)来维护dist数组,算法复杂度可以提升到O((n+m)logn);

-优先队列的作用是替代每次迭代时找到离起点最近的点(可以用set集合替代)

struct Node{
    int y,v;
    Node(int _y,int _v){ y=_y;v=_v;};
};
vector<Node> edge[N+5];
set<pair<int,int>> q;//set底层是红黑树,有序的,先对pair->first进行排序,然后回pair->seconde进行排序
vector<Node>  edge[N+5];
int n,m,dist[N+5];
int Dijkstra(int s,int t){
    memset(dist,127,sizeof(dist));
    dist[s]=0;
    q.clear();
    for(int i=1;i<=n;i++)
        q.insert(make_pair(dist[i],i));
    while(!q.empty()){
         int x=q.begin()->second;
         q.erase(q.begin());
        if(x==t||dist[x]==-1) break;
        for(auto i:edge[x]){
            if(dist[x]+i.v<dist[i.y]){
                q.erase(make_pair(dist[i.y],i.y));
                dist[i.y]=dist[x]+i.v;
                q.insert(make_pair(dist[i.y].i.y));
            }
        }
    }
    return dist[t];
}
//使用set 不能直接修改数据,要先erase在insert,因为set内部是红黑树实现,有序的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f;
const ll maxn = 1e5 + 5;
struct Edge{
	int y,v;
	Edge(int _y,int _v){
		y=_y;
		v=_v;
	}
};
vector<Edge> edge[200005];
int n,m,k;
int dist[maxn];
bool flag[maxn];
set<pair<int,int>> s;
int Dijkstra(int p,int q)
{
     memset(dist,127,sizeof(dist));
	 memset(flag,false,sizeof(flag));
	 s.clear();
	 dist[p]=0;
	 for(int i=1;i<=n;i++) s.insert(make_pair(dist[i],i));
	 for(;!s.empty();)
	 {
		int x=s.begin()->second;
		s.erase(s.begin());
		if(x==q||dist[x]>1<<30) break;
        flag[x]=true;
	    for(auto it:edge[x])
		{
			 if(it.v+dist[x]<dist[it.y])
			 {
				s.erase(make_pair(dist[it.y],it.y));
				dist[it.y]=it.v+dist[x];
				s.insert(make_pair(dist[it.y],it.y));
			 }
		}    
	 }
	 if(dist[q]>1<<30)
	 return -1;
	 else
	 return dist[q];
}
void solve()
{
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		edge[x].push_back(Edge(y,z));
	}
	for(int i=1;i<=k;i++)
	{   int x,y;
	    cin>>x>>y;
		cout<<Dijkstra(x,y)<<'\n';
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n = 1;
	while (n--)
	{
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值