图专题

代码来源:晴神《算法笔记》!!

图的储存

  • 邻接矩阵

  • 邻接表

struct Node{
	int v;  //边的终点编号 
	int w;  //边权 
	Node(int _v, int _w) : v(_v), w(_w) {}  //构造函数 
};

vector<Node> Adj[N]; 

Adj[1].push_back(Node(3,4));   //添加边 

图的遍历

1.DFS 版本
  • 邻接矩阵
void dfs(int u, int depth){
	vis[u] = true;
	for(int v = 0; v < n; v++){
		if(vis[v] == false && g[u][v] != inf)
			dfs(v, depth + 1);
	}
} 
void dfstrave(){
	for(int u = 0; u < n; u++){
		if(vis[u] == false){
			dfs(u,1);
		}
	}
}
  • 邻接表
vector<int> Adj[maxn];
int n;
bool vis[maxn] = {false};

void dfs(int u, int depth){
	vis[u] = true;
	for(int i = 0; i < Adj[u].size(); i++){
		int v = Adj[u][i];
		if(vis[v] == false)
			dfs(v,depth + 1);
	}
}
2.BFS版本
  • 邻接矩阵
int n, g[maxn][maxn];
bool inq[maxn] = {false};

void bfs(int u){
	queue<int> q;
	q.push(u);      //是push不是push_back 
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();  //是front不是top 
		q.pop();
		for(int v = 0; v < n; v++){
			if(inq[v] ==false && g[u][v] != inf){
				q.push(v);
				inq[v] = true;
			}
		}
	}
}
void bfstrave(){
	for(int u = 0; u < n; u++){
		if(inq[u] == false)
			bfs(u); 
	}
}
  • 邻接表
vector<int> Adj[maxn];
int n;
bool inq[maxn] = {false};

void bfs(int u){
	queue<int> q;
	q.push(u);
	inq[u] = true;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		for(int i = 0; i < Adj[u].size(); i++){
			int v = Adj[u][i];
			if(inq[v] == false){
				q.push(v);
				inq[v] = true;
			}
		}
	} 
}

最短路径

Dijkstra算法

边权非负

  • 伪代码
//s起点
dijkstra(g,d[],s){
	初始化;
	for(循环n次){
		u = d[u]最小的还未访问的顶点标号;
		记u被访问;
		for(从u出发能到达的顶点v){
			if(v未访问&&以u为中介点可以更新d[v]){
				优化d[v]; 
				//令v的前缀为u 
			} 
		} 
	} 
} 
  • 邻接表
struct Node{
	int v,dis;//dis为边权 
};
vector<Node> Adj[maxn];
int n;
int d[maxn];
bool vis[maxn] = {false};

void dijkstra(int s){
	fill(d, d + maxn, inf);
	d[s] = 0;
	for(int i = 0; i < n; i++){
		int u = -1, MIN = inf;
		for(int j = 0; j < n; j++){
			if(vis[j] == false && d[j] < MIN){
				MIN = d[j];
				u = j; 
			}
		}
		if(u == -1) return;
		vis[u] = true;
		for(int j = 0; j < Adj[u].size(); j++){
			int v = Adj[u][j].v;
			if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
				d[v] = d[u] + Adj[u][j].dis;
				//pre[v] = u;
			}
		}
	}
} 
  • 打印最短路径
void dfs(int s, int v){
	if(v == s){
		printf("%d\n",s);
		return;
	}
	dfs(s,pre[v]);
	printf("%d\n",v);
}
  • 增加第二标尺(边权、点权、最短路径条数)
//增加边权,cost[u][v],c[]  初始时c[s]为0,其余为inf
for(int v = 0; v < n; v++){
	if(vis[v] == false && g[u][v] != inf){
		if(d[u] + g[u][v] < d[v]){
			d[v] = d[u] + g[u][v];
			c[v] = c[u] + cost[u][v];
		}
		else if(d[u] + g[u][v] == d[v] && c[u] + cost[u][v] < c[v]){
			c[v] = c[u] + cost[u][v];
		}
	}
}
//增加点权,weight[u],w[]  初始时w[s]为weight[s],其余为0 略 
//最短路径条数,num[]  初始时只有num[s]为1,其余为0
for(int v = 0; v < n; v++){
	if(vis[v] == false && g[u][v] != inf){
		if(d[u] + g[u][v] < d[v]){
			d[v] = d[u] + g[u][v];
			num[v] = num[u]; 
		}
		else if(d[u] + g[u][v] == d[v]){
			num[v] += num[u];
		}
	}
}
  • Dijkstra+DFS
//Dijkstra 
//int pre[maxn]修改为vector<int> pre[maxn]或set<int> pre[maxn]
if(d[u] + g[u][v] < d[v]){
	d[v] = d[u] + g[u][v];
	pre[v].clear();
	pre[v].push_back(u);
} 
else if(d[u] + g[u][v] == d[v]){
	pre[v].push_back(u);
}

//DFS
int optvalue;
vector<int> path, temppath;
void dfs(int v){
	if(v == dt){
		temppath.push_back(v);
		int value;
		计算value值;  //倒着计算 
		if(value优于optvalue){
			optvalue = value;
			path = temppath;
		} 
		temppath.pop_back();
		return ;
	}
	temppath.push_back(v);
	for(int i = 0; i < pre[v].size(); i++){
		dfs(pre[v][i]);
	}
	temppath.pop_back();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值