Dijkstra
(加点法)
- 适用于边权为正的情况
- 适用于有向图和无向图
- 可用于计算正权图上的单源最短路,即从单个源点出发,到所有结点的最短路。
伪代码
清除所有点的标号
设d[0] = 0,其他d[i] = INF
循环n次{
在所有未标号的结点中,选出d值最小的结点x
给结点x标记
对于从x出发的所有边(x,y),更新d[y] = min{d[y], d[x]+w(x,y)}
}
memset(v, 0, sizeof(v));
for(int i = 0; i < n; i++)
d[i] = (i == 0 ? 0 : INF);
for(int i = 0; i < n; i++){
int x,m = INF;
for(int y = 0; y < n; y++)
if(!v[y] && d[y] <= m)
m = d[x = y];
v[x] = 1;
for(int y = 0; y < n; y++)
d[y] = min(d[y], d[x] + w[x][y]);
}
const int INF = 100;
//寻找d最小的结点
int Min(int dist[], int vertexNum){
int i,k;
for(i = 0,k = 0;i<vertexNum; i++)
if((dist[i]!=0)&&(dist[i]<dist[k]))
k=i;
return k;
}
void Dijkstra(int v){
//num:已被标记的点的个数
int num,dist[MaxSize];
for(int i=0;i<vertexNum;i++){
dist[i] = edge[v][i];
if(dist[i]!=INF)
path[i] = vertex[v]+vertex[i];
else
path[i] = "";
}
for(num = 1;num<vertexNum;num++){
k = Min(dist,vertexNum);
cout<<path[k]<<dist[k];
//更新d
if(dist[i]>dist[k]+edge[k][i]){
dist[i] = dist[k]+edge[k][i];
path[i] = path[k]+vertex[i];
}
dist[k]=0;
}
}
Bellman-Ford
- 路径包含负权
for(int i = 0; i < n; i++)
d[i] = INF;
d[0] = 0;
//最短路径最多只经过(起点不算)n-1个结点
for(int k = 0; k < n-1; k++)
for(int i = 0; i < m; i++){
int x = u[i], y = v[i];
if(d[x] < INF)
d[y] = min(d[y], d[x]+w[i]);
}
Floyd
(加边法)
const int INF = 100;
void Floyd(){
int dist[MaxSize][MaxSize];
string path[MaxSize][MaxSize];
for(int i=0; i<vertexNum; i++)
for(int j=0; j<vertexNum; j++){
dist[i][j] = edge[i][j];
if(dist[i][j] !=INF)
path[i][j] = vertex[i] + vertex[j];
else
path[i][j] = "";
}
for(int k=0; k<vertexNum; k++)
for(int i=0; i<vertexNum; i++)
for(int j=0; j<vertexNum; j++)
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j]=dist[i][k]+dist[k][j];
psth[i][j]=path[i][k]+path[k][j];
}
}
SPFA
- 适用于含负权值的图
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
final static int Max = 200010;
final static int INF = 1<<30;
static class edge{
int to, next, w;
public edge(int to, int next, int w) {
// TODO Auto-generated constructor stub
this.to = to;
this.next = next;
this.w = w;
}
}
static edge e[] = new edge[Max];
static int head[] = new int[Max];
static int cnt = 0;
static boolean vis[] = new boolean[Max];
static int dis[] = new int[Max];
private static void add(int from, int to, int w) {
e[cnt] = new edge(to, head[from], w);
head[from] = cnt++;
}
private static void spfa(int a) {
Queue<Integer> q = new LinkedList<Integer>();
dis[a] = 0;
vis[a] = true;
q.add(a);
while(!q.isEmpty()) {
int u = q.poll(), t;
vis[u] = false;
for(int i = head[u]; i != -1; i = e[i].next) {
t = e[i].to;
if(dis[t] > dis[u] + e[i].w && !vis[t]) {
dis[t] = dis[u] + e[i].w;
q.add(t);
vis[t] = true;
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n,m;
n = sc.nextInt();
m = sc.nextInt();
Arrays.fill(dis, INF);
Arrays.fill(vis, false);
Arrays.fill(head, -1);
for(int i = 0; i < m; i++) {
int u, v, l;
u = sc.nextInt();
v = sc.nextInt();
l = sc.nextInt();
add(u, v, l);
}
spfa(1);
for(int i = 2; i <= n; i++)
System.out.println(dis[i]);
}
}
229

被折叠的 条评论
为什么被折叠?



