POJ-图论-最短路模板
一、Floyd算法
刚读入数据时,G为读入的图邻接矩阵,更新后,G[i][j]表示结点i到结点j的最短路径长度
int G[N][N];//二维数组,其初始值即为该图的邻接矩阵
1.init():初始化图邻接矩阵
void init() { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { G[i][j] = -1;//初始化邻接矩阵,用-1代表无穷 } G[i][i] = 0;//初始化,自己到自己的路径长度为0 } }
2.floyd():更新最短路径
void floyd() { for (int k = 1; k <= n; k++)//从1至n循环k { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++)//遍历所有的i,j { if (G[i][k] == -1 || G[k][j] == -1)continue; if (G[i][j] == -1 || G[i][k] + G[k][j] < G[i][j])G[i][j] = G[i][k] + G[k][j]; } } } }
例 5.5 最短路
模板代码
#include<cstdio> const int N = 105; int G[N][N]; int n, m; void init() { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { G[i][j] = -1;//初始化为无穷 } } for (int i = 1; i <= n; i++)G[i][i] = 0;//自己到自己距离是0 } void floyd() { for (int k = 1; k <= n; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (G[i][k] == -1 || G[k][j] == -1)continue; else if (G[i][j] == -1 || G[i][j] > G[i][k] + G[k][j])G[i][j] = G[i][k] + G[k][j]; } } } } int main() { while (scanf("%d%d", &n, &m) != EOF) { if (n == 0 && m == 0)break; init(); int x, y, t; for (int i = 0; i < m; i++) { scanf("%d%d%d", &x, &y, &t); G[x][y] = G[y][x] = t; } floyd(); printf("%d ", G[1][n]); } return 0; }
二、Dijkstra算法
G为图邻接矩阵,G[i][j]表示读入的i到j的距离,后面不再更新。d[]为距离数组,d[i]表示结点i到起点的最短距离。vis[N]为访问数组,记录各结点的访问情况。
int G[N][N]; // 图邻接矩阵 int d[N]; // 表示起点到各结点的最短距离 bool vis[N] = { false }; // 表示各结点被访问过与否
1.init():初始化邻接矩阵,到自身的距离为0
void init() // 初始化 { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i == j) G[i][j] = 0; else G[i][j] = INF; } } }
2.Dijkstra(int start):初始化d[]之后,进行n次循环,每次先确定与起点直接相连的距离最小结点u及其距离d[u],再更新起点到其他结点v的距离d[v]。
void Dijkstra(int start) { for (int i = 1; i <= n; i++) d[i] = INF;//可达距离都初始化为无穷 d[start] = 0; // 起初只有start结点可达 for (int i = 1; i <= n; i++) { int u = -1; // 距离最近的结点u,初始化为-1 int min = INF; // min存放最小的d[u],初始化为无穷 for (int j = 1; 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 = 1; v <= n; v++)//由新得到的点更新后面所有点 { // 此处d[u]有一个相加操作,所以在设置很大整数时不能设置为0x7fffffff,会导致溢出 if (vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]) d[v] = d[u] + G[u][v]; } } }
例 5.5 最短路
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N = 105; const int INF = 0x3fffffff; int n, m; int G[N][N]; int d[N];//起点到各点的距离 bool vis[N] = { false }; void init() { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { G[i][j] = INF; } G[i][i] = 0; } for (int i = 1; i <= n; i++) { d[i] = INF; vis[i] = false; } } void djkstra(int start) { d[start] = 0; for (int i = 1; i <= n; i++)//每次加入一个结点(这时连起点都还没加入) { int u = -1;//最近的结点 int min = INF;//最近的距离值 for (int j = 1; j <= n; j++) { if (vis[j] == false && d[j] < min) { min = d[j]; u = j; } } if (u == -1)return;//无路可走 vis[u] = true; for (int v = 1; v <= n; v++)//更新其他节点 { if (vis[v] == false && G[u][v] != INF && d[v] > d[u] + G[u][v])d[v] = d[u] + G[u][v]; } } } int main() { while (scanf("%d%d", &n, &m) != EOF) { if (n == 0 && m == 0)break; init(); for (int i = 0; i < m; i++) { int a, b, t; scanf("%d%d%d", &a, &b, &t); G[a][b] = G[b][a] = t; } djkstra(1); printf("%d ", d[n]); } return 0; }