Day 47 算法笔记之提高篇(4)10.4 最短路径

目录

1.Dijkstra算法

1.1邻接矩阵

1.2邻接表

1.3路径

1.4新增边权

1.5新增点权

1.6最短路径数

1.7Emergency

1.8配合DFS

1.8.1找出路径

1.8.2DFS遍历

1.8.3  Travel Plan


1.Dijkstra算法

1.1邻接矩阵

const int maxv=1000;
const int inf = 100000000;

int n,g[maxv][maxv];
int d[maxv];
bool vis[maxv] = {false};

void dijkstra(int s){
	fill(d,d+maxv,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){
				u = j;
				min = d[j];
			}
		}
		if(u==-1) return;
		vis[u] = true;
		for(int v=0;v<n;v++){
			if(vis[v]==false&&g[u][v]!=inf&&d[u]+g[u][v]<d[v]){
				d[v] = d[u] + g[u][v];
			}
		}
	}
}

1.2邻接表

const int maxv=1000;
const int inf = 100000000;

struct node{//目标顶点,边权 
	int v,dis;
};
vector<node> adj[maxv];
int n;
int d[maxv];
bool vis[maxv] = {false};

void dijkstra(int s){
	fill(d,d+maxv,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){
				u = j;
				min = d[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
			}
		}
	}
}

1.3路径

void dfs(int s,int v){
	if(v==s){
		printf("%d\n",s);
		return;
	}
	dfs(s,pre[v]);
	printf("%d\n",v);
}

1.4新增边权

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];
		}
	}
}

1.5新增点权

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];
			w[v] = w[u] + weight[v];
		}else if(d[u]+g[u][v]==d[v]&&w[u]+weight[v]>w[v]){
			w[v] = w[u] + weight[v];
		}
	}
}

1.6最短路径数

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];
		}
	}
}

1.7Emergency

#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxv = 510;
const int inf = 1000000000;

int n,m,st,ed,g[maxv][maxv],weight[maxv];
int d[maxv],w[maxv],num[maxv];
bool vis[maxv] = {false};

void dijkstra(int s){
	fill(d,d+maxv,inf);
	memset(w,0,sizeof(w));
	d[s] = 0;
	w[s] = weight[s];
	num[s] = 1;
	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){
				u = j;
				min = d[j];
			}
		}
		
		if(u==-1) return;
		vis[u] = true;
		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];
					w[v] = w[u] + weight[v];
					num[v] = num[u];
				}else if(d[u]+g[u][v]==d[v]){
					if(w[u]+weight[v]>w[v]){
						w[v] = w[u] + weight[v];
					}
					num[v] += num[u];
				}
			}
		}
	}
}

int main(){
	
	scanf("%d%d%d%d",&n,&m,&st,&ed);
	for(int i=0;i<n;i++){
		scanf("%d",&weight[i]);
	}
	
	int u,v;
	fill(g[0],g[0]+maxv*maxv,inf);
	
	for(int i=0;i<m;i++){
		scanf("%d%d",&u,&v);
		scanf("%d",&g[u][v]);
		g[v][u] = g[u][v];
	}
	
	dijkstra(st);
	printf("%d %d\n",num[ed],w[ed]);
	

	
	return 0;
}

1.8配合DFS

1.8.1找出路径

const int maxv = 510;
const int inf = 1000000000;

vector<int> pre[maxv];
void dijkstra(int s){
	fill(d,d+maxv,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){
				u = j;
				min = d[j];
			}
		}
		if(u==-1) return;
		vis[u] = true;
		
		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];
					pre[v].clear();
					pre[v].push_back(u);
				}else if(d[u]+g[u][v]==d[v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}

1.8.2DFS遍历

int optvalue;
vector<int> pre[maxv];
vector<int> path,temppath;
void dfs(int v){
	
	if(v==st){
		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();
}

1.8.3  Travel Plan

#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxv = 510;
const int inf = 1000000000;

int n,m,st,ed,g[maxv][maxv],cost[maxv][maxv];
int d[maxv],c[maxv],pre[maxv];
bool vis[maxv]={false};

void dijkstra(int s){
	fill(d,d+maxv,inf);
	fill(c,c+maxv,inf);
	for(int i=0;i<n;i++){
		pre[i] = i;
	}
	d[s] = 0;
	c[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){
				u = j;
				min = d[j];
			}
		}
		if(u==-1) return;
		vis[u] = true;
		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];
					pre[v] = u;
				}else if(d[u]+g[u][v]==d[v]){
					if(c[u]+cost[u][v]<c[v]){
						c[v] = c[u] + cost[u][v];
						pre[v] = u;
					}
				}
			}
		}
	}
}

void dfs(int v){
	if(v==st){
		printf("%d ",v);
		return;
	}
	dfs(pre[v]);
	printf("%d ",v);
}

int main(){
	
	scanf("%d%d%d%d",&n,&m,&st,&ed);
	int u,v;
	fill(g[0],g[0]+maxv*maxv,inf);
	for(int i=0;i<m;i++){
		scanf("%d%d",&u,&v);
		scanf("%d%d",&g[u][v],&cost[u][v]);
		g[v][u] = g[u][v];
		cost[v][u] = cost[u][v];
	}
	dijkstra(st);
	dfs(ed);
	printf("%d %d\n",d[ed],c[ed]);
	
	return 0;
}
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxv = 510;
const int inf = 1000000000;

int n,m,st,ed,g[maxv][maxv],cost[maxv][maxv];
int mincost=inf;
int d[maxv];
bool vis[maxv]={false};

vector<int> pre[maxv];
vector<int> temppath,path;

void dijkstra(int s){
	fill(d,d+maxv,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){
				u = j;
				min = d[j];
			}
		}
		if(u==-1) return;
		vis[u] = true;
		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];
					pre[v].clear();
					pre[v].push_back(u);
				}else if(d[u]+g[u][v]==d[v]){
					pre[v].push_back(u);
				}
			}
		}
	}
}

void dfs(int v){
	if(v==st){
		temppath.push_back(v);
		int tempcost=0;
		for(int i=temppath.size()-1;i>0;i--){
			int id=temppath[i],idnext=temppath[i-1];
			tempcost += cost[id][idnext];
		}
		if(tempcost<mincost){
			mincost = tempcost;
			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();
}

int main(){
	
	scanf("%d%d%d%d",&n,&m,&st,&ed);
	int u,v;
	fill(g[0],g[0]+maxv*maxv,inf);
	fill(cost[0],cost[0]+maxv*maxv,inf);
	for(int i=0;i<m;i++){
		scanf("%d%d",&u,&v);
		scanf("%d%d",&g[u][v],&cost[u][v]);
		g[v][u] = g[u][v];
		cost[v][u] = cost[u][v];
	}
	dijkstra(st);
	dfs(ed);
	for(int i=path.size()-1;i>=0;i--){
		printf("%d ",path[i]);
	}
	printf("%d %d\n",d[ed],mincost);
	
	return 0;
}

おすすめ

転載: blog.csdn.net/aixiaoxiao13/article/details/121610448