图的存储

图的存储

直接存边

使用一个数组(结构体数组)来存边,数组中的每个元素都包含一条边的起点与终点(带边权的图还包含边权)。(或者使用多个数组分别存起点,终点和边权。)

应用

由于直接存边的遍历效率低下,一般不用于遍历图。

在 Kruskal 算法 中,由于需要将边按边权排序,需要直接存边。

在有的题目中,需要多次建图(如建一遍原图,建一遍反图),此时既可以使用多个其它数据结构来同时存储多张图,也可以将边直接存下来,需要重新建图时利用直接存下的边来建图。

邻接矩阵

a[i][j] = 3; 代表 i 到 j 的路程为 3

应用

邻接矩阵只适用于没有重边(或重边可以忽略)的情况。

其最显著的优点是可以 查询一条边是否存在。

由于邻接矩阵在稀疏图上效率很低(尤其是在点数较多的图上,空间无法承受),所以一般只会在稠密图上使用邻接矩阵。

邻接表

使用一个支持动态增加元素的数据结构构成的数组,如 vector<int> edge[n + 1] 来存边,其中 edge[u] 存储的是点 的所有出边的相关信息**(终点、边权等)。**

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 10000005;

int n, m;
int dist[N];
struct edge {
	int to, cost;
	edge(int to, int cost) {
		this->to = to;
		this->cost = cost;
	}
};
vector<edge> e[N];
int pre[N];//记录前驱
void dij(int s){
	priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que; // 默认优先第一个元素排序 
	memset(pre, -1, sizeof pre);
	memset(dist, 0x3f, sizeof(dist));
    dist[s] = 0;
    que.push(make_pair(0,s));//把起点压入队列
    while(!que.empty()) {
    	pair<int, int> p = que.top();
    	que.pop();
    	//顶点的编号
        int v = p.second;
        if(dist[v] < p.first) continue; // 说明这个点是被访问过的
		for(int i = 0; i < e[v].size(); i++) {
			edge node = e[v][i];
			if(dist[node.to] > dist[v] + node.cost) {
				dist[node.to] = dist[v] + node.cost;
				que.push(make_pair(dist[node.to], node.to));
				pre[node.to] = v; // 记录前驱节点 
			}
		} 
    	
	}
	
}
int main() {
	int n, m;
	cin >> n >> n;
	for(int i = 1; i <= m; i++) {
		int x, y, z;
		cin >> x >> y >> z;
		e[x].push_back(edge(y, z));
	}
	int s = 1;
	dij(s);
	
	for(int i = 0; i < n; i++) {
		cout << dist[i] << ' ' << endl;
	}
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值