存图方式

//code by virtualtan 寒七

//注:本代码包括了三种,可能有点杂

加边:

#include <cstdio>
#include <algorithm>

#define MAXN 1111
#define MAXM 2222222

int n, m, cnt;
int a[MAXN][MAXN], b[MAXN][MAXN];

struct edge {
	int x, y, val, next;//起点   终点   权   上一条起点相同的边 的编号 
}e[MAXM];

void add_edge(int x, int y, int val) {
	cnt++;//边的序数 
	e[cnt].x = x;
	e[cnt].y = y;
	e[cnt].val = val;
	e[cnt].next = head[x];//head【x】表示cnt 之前的一条首顶点为 x 的边 的编号 ——可以直接跳转到e[].next 
	head[x] = cnt;//更新首顶点为 x 的最后一条边 
	return ;
}

//有向无权图 
int main() {
	scanf("%d%d", &n, &m);
	memset(a, 0x3f, sizeof(a));//主要是针对矩阵
	for(int i = 1; i <= n; i++) {
		a[i][i] = 0;//这个应该是解决自环问题
	}
	for(int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d%d", &x, &y);
		//邻接矩阵
		a[x][y] = 1;
		//邻接表 
		b[x][++b[x][0]] = y;
		//链式前向星(重点)
		add_edge(x, y, 1); 
	}

//补:
有权图解决两节点间的重边问题,只需加一个判断就行:

if(a[i][j] > w) {
	a[i][j] = w;
}

或者用min(a[i][j] , w);个人喜好

还有注意自环问题,特殊处理

图的遍历

一般采用搜索算法

遍历出所有与1相连的边:

//邻接矩阵做法
	for(int i = 1; i <= n; i++) {
		if(a[1][i] == 1) {
      //大体是这样就行
		}
	}
//邻接表做法
	for(int i = 1; i <= b[1][0]; i++) {
		b[1][i];
	}
	//        因为e[1].next最开始初始化的时候给它赋值的 head[1] 等于0(默认的0) 
	//    从后向前找   “i”表示'i > 0'   i = e[i].next 起点为x(找所有与x相连的点)的最后一条边 
	//		此处x = 1; 
	for(int i = head[1]; i; i = e[i].next) {
		int x = e[i].x, y = e[i].y, val = e[i].val;
	}
}

最后附上:
/*邻接表 的模样
0 1 2 3 4 5
1 2 3 4
2 4
3 3
4 5
5 4 */

/*测试数据
5
1 2
2 4
1 4
5 4
4 5
1 3
*/
链式前向星的作用:
我一开始总是因为可以直接求出最短路的
遍历时,对于一个点u,枚举这个点所有向外的边

自己选择的路,跪着也要走完。
原文地址:https://www.cnblogs.com/tyner/p/10701731.html