算法导论学习笔记-基础图算法

一、图的表示
两种形式:
[1]邻接表:

struct Edge{
	int from,to,cap,flow;//以最大流问题的数据结构为例
	//from起点u;to终点v;
}
vector<Edge>edges;//保存每条边的信息并编号
int n,m;//n记录点数V,m记录边数量E
vector<int> G[MAXN];//G[u][v]存放从u出发到v的边在edges向量中的下标;
//G[u]存放了以u为起点的所有边在edges向量中的下标;
void add_edge(int from,int to,int cap){//添加边操作
	edges.push_back((Edge){from,to,cap,0});//边
	edges.push_back((Edge){to,from,0,0});//残量网络反向边
	int m = edges.size();
	G[from].push_back(m-2);//G[from]包含以from为起点的所有边
	G[to].push_back(m-1);//记录对应边在edges中的下标
}

邻接表表示由一个包含V条链表的数组Adj组成,每个节点有一条链表,对于每个节点u∈V,有邻接表Adj[u]所包含所有与节点u邻接的节点。
我的邻接表没有使用指针,因为目前我在图算法的学习中暂时没有碰到需要删除边的操作,所以就先使用vector来代替链表,这样写起来也更方便一点。
[2]邻接矩阵

//数组形式
int a[MAXN][MAXN];
void add_edge(int from,int to,int dis){
	a[i][j]=min(a[i][j],dis);//这里用最短路为例,如果存在重边则取最短的
}
//vector向量形式
vector< vector<int> > a(MAXN,vector<int>(MAXN,0));//二维vector的使用
void add_edge(int u,int v,int dis){
	a[u][v]=dis;
}


以Adj[1]为例,链表头节点后面又2和5两个,表示e(1,2)和e(1,5)两条边。
算法导论中说可以用邻接表存放边的权重,如最短路中的distance和最大流中的cap。我代码里通过在结构体里面多增加了一个元素。

课后练习:
1-1:
Q:给定邻接链表,需要多长时间才能计算出每个节点的出度和入度?
A:出度的话如果是vector实现的化,直接调用size()可以O(1),链表的话应该是O(E);入度的话如果在最大流问题中,因为储存了残量网络中的反向边,所以也可以O(1),其他情况应该需要给O(e(V*E);
//后面的感觉有点难以后再写吧2333
二、广度优先算法BFS
[1]算法思想
Prim最小生成树算法和Dijkstra单源最短路径算法都使用了类似广度优先搜索的思想。
给定图G=(V,E)和一个可以识别的源节点s,广度优先可以发现从源节点s到达的所有节点。
在广度优先搜索树里从节点s到v的简单路径所对应的就是G中节点s到v的经过边数最少的路径。这个算法适用于有向图和无向图。
广度优先搜索,也就是再发现所有距离节点s为k的所有点之后,才会发现离源点距离为k+1的点。这里的距离也是指经过的边数,如果是最短路问题中的距离其实是边权值之和。
我是用结构体和stl队列容器实现的bfs;

struct Node{//结构体根据需求来,这里以二维的坐标节点为例
	int x,y,steps;//x,y和步数
}
queue<Node> q;
void bfs(int startx,int starty){
	q.push(Node(startx,starty,0));//推入第一个起点进队列
	while(!q.empty()){
		Node now;
		now=q.front();//先进先出,取出优先级最高的即离起点距离最短的
		q.pop();
		if(now.x==desx&&now.y==desy){//如果到达目标节点
			输出语句
			break;
		}
		for(int i=0;i<4;i++){
			if(OK(now.x+dir[i][0],now.y+dir[i][1]){//如果到这个点是可以有路的
				q.push(Node(now.x+dir[i][0],now.y+dir[i][1],now.steps+1));
				//把这个点推入队列。
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值