Dijkstra-POJ2387邻接表和优先队列的优化

本文深入探讨了Dijkstra算法的原理与应用,通过详细的代码示例,展示了如何使用邻接表和优先队列实现该算法,以解决图中单源最短路径问题。文章覆盖了算法的初始化、松弛操作、堆的使用以及去重边的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstring>
#include <map>
#include <functional>
#include <vector>
using namespace std;

const int INF = 1<<29;
const int maxn = 1e3+5;

struct node {
	int cost, to;
	node (){};
	node (int a, int b) {
		cost = b;
		to = a;
	}
	bool operator < (const node& s) const {
		return cost > s.cost;
	}
};
vector <node> G[maxn];  //建立一个邻接表
int vis[maxn];  //标记结点是否走过
int dist[maxn]; //表示从起点到结点的距离

int T, N;

int Dijkstra(int start) {

	priority_queue <node> pq;
	pq.push(node(start,0)); //将起点存入队列中
	memset(vis, 0, sizeof(vis));    //memset函数不能初始化为无穷大
	fill(dist, dist+N+1, INF);  //所以还是用fill函数吧!
    dist[start] = 0;    //不能掉,这里被坑了很久!

	while(!pq.empty()) {
		node t = pq.top();
		pq.pop();
		int v = t.to;
		if (vis[v]) continue;   //避免一个点后面遍历多次!
		vis[v] = 1; //前面语句判断这个点是否遍历过,然后标记现在已经遍历了
        for (vector <node>:: iterator j = G[v].begin(); j != G[v].end(); j++) {
            node st = *j;
            if (st.cost + dist[v] < dist[st.to] && !vis[st.to]) {   //不能走自己,也不能走重复的结点
                dist[st.to] = st.cost + dist[v];
                pq.push(node(st.to,dist[st.to]));   //更新了的有效点都放进堆里
            }
		}
	}
	return dist[N]; //返回从1到N的距离值
}
int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	while(cin >> T >> N) {
        for (int i = 1; i <= N; i++) {  //邻接表的初始化
            if (!G[i].empty()) {
                G[i].clear();
            }
        }
        if (N == 1) {
            cout << 0 << endl;
            continue;
        }
		while(T--) {
			int a, b, c;
			cin >> a >> b >> c;
			G[b].push_back(node(a,c));
			G[a].push_back(node(b,c));  //去重边
		}
		cout << Dijkstra(1) << endl;
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值