图的存储

图的存储

:代码均为对向图处理

1.直接存边

用于对边的预处理,不过多赘述

2.邻接矩阵

使用一个二维数组\(g[u][v]\) 表示\(u\) 点是否连接着\(v\) 点。

存储:

for(int i = 1; i <= m; i++){
    int u, v;
    cin >> u >> v;
    a[u][v] = 1;
}

遍历

void dfs(int u){
	if(vis[u]) return;
    vis[u] = 1;
    for(int v = 1; v <= n; v++){
        if(a[u][v])
        	dfs(v);
    }
}

找边:

bool find_edge(int u, int v){//找边(u,v)
    if(a[u][v]) return true;
    return false;
}

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

优点为可以\(O(1)\) 查询是否有这条边

3.邻接表

使用一个可以动态增加元素的数组,如\(vector\) 来存图。

存储

vector<int>g[N];//N为点的个数
for(int i = 1; i <= m; i++){
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
}

遍历

void dfs(int u){
	if(vis[u]) return;
    vis[u] = 1;
    for(int v:g[u]){
        dfs(v);
    }
}

找边:

bool find_edge(int u, int v){
    for(int i:g[u]){
        if(i == v) return true;
    }
    return false;
}

可以定义\(g[N]\) 为一个结构体存边权等数据。

4.链式前向星

运用链表的思想实现的邻接表

存储:

// head[u] 和 cnt 的初始值都为 -1
int head[N];
struct node{
    int to, nxt;
}g[M];
int cnt;
void add(int u, int v){
    g[++cnt].to = v;   // 当前边的终点
    g[cnt].nxt = h[u]; // 当前边的后继
    head[u] = cnt;        // 起点 u 的第一条边
}

for(int i = 1; i <= m; i++){
    int u, v;
    cin >> u >> v;
    add(u, v);
}

遍历:

void dfs(int u){
    if(vis[u]) return;
    vis[u] = 1;
    for(int i = head[u]; ~i; i = g[i].nxt){//~i等同于i!=-1
    	dfs(g[i].to)
	}
}

找边:

bool find_edge(int u, int v){
	for(int i = haed[u]; ~i; i = g[i].nxt){
		if(g[i].to == v) return true;
	}
    return false;
}

不能方便地对一个点的出边进行排序。

优点是边是带编号的,而且如果 cnt 的初始值为奇数,存双向边时 i ^ 1 即是 i 的反边。

(常用于网络流)

posted @ 2026-05-30 14:35  HEGVDV  阅读(13)  评论(0)    收藏  举报