本文是最短路径算法整理的第二篇,想阅读第一篇的朋友可以点击以下链接:
http://blog.youkuaiyun.com/hjd_love_zzt/article/details/26739593
这一篇博客继续以一些OJ上的题目为载体,整理一下最短路径算法。会陆续的更新。。。
1、HDU 2544
题目与分析:这道题抽象一下,还是:“求a到b的最短路径”。。所需要的基本条件是:点数、边数、起点、终点
以下给出floyd、dijkstra、bellmanford三种最短路径算法关于这道题的解法:
1)floyd
/*
* HDU_2544.cpp
*
* Created on: 2014年5月31日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 105;
const int inf = 10000005;
int e[maxn][maxn];
int n;
void initial(){
int i;
int j;
for(i = 1 ; i <= n ; ++i){
for(j = 1 ; j <= n ; ++j){
if(i == j){
e[i][j] = 0;
}else{
e[i][j] = inf;
}
}
}
}
void floyd(){
int k;
int i;
int j;
for(k = 1 ; k <= n ; ++k){
for(i = 1 ; i <= n ; ++i){
for(j = 1 ; j <= n ; ++j){
if(e[i][j] > e[i][k] + e[k][j]){
e[i][j] = e[i][k] + e[k][j];
}
}
}
}
}
int main(){
int m;
while(scanf("%d%d",&n,&m),n||m){
initial();
int i;
for(i = 1 ; i <= m ; ++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
e[a][b] = e[b][a] = c;
}
floyd();
printf("%d\n",e[1][n]);
}
return 0;
}
2)dijkstra
/*
* HDU_2544.cpp
*
* Created on: 2014年5月31日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 105;
const int inf = 10000005;
int n;
int s[maxn];
int dis[maxn];
int map[maxn][maxn];
int target;
int dijkstra(int v){
int i;
for(i = 1 ; i <= n ; ++i){
s[i] = 0;
dis[i] = map[v][i];
}
// dis[v] = 0;//其实上面的操作已经包含这个意思了
int j;
for(i = 1 ; i < n ; ++i){
int min = inf;
int pos;
for(j = 1 ; j <= n ; ++j){
if(!s[j] && dis[j] < min){
min = dis[j];
pos = j;
}
}
s[pos] = 1;
for(j = 1 ; j <= n ; ++j){
if(dis[j] > dis[pos] + map[pos][j]){
dis[j] = dis[pos] + map[pos][j];
}
}
}
return dis[target];
}
int main(){
int m;
while(scanf("%d%d",&n,&m),n||m){
int i;
int j;
for(i = 1 ; i <= n ; ++i){
for(j = 1 ; j <= n ; ++j){
if(i == j){
map[i][j] = 0;
}else{
map[i][j] = inf;
}
}
}
for(i = 1 ; i <= m ; ++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
map[a][b] = map[b][a] = c;
}
target = n;
int result = dijkstra(1);
printf("%d\n",result);
}
return 0;
}
3)bellmanford
/*
* HDU_2544.cpp
*
* Created on: 2014年5月31日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
using namespace std;
struct Edge{
int u;
int v;
int weight;
};
const int maxn = 105;
const int maxm = 10005;
const int inf = 1000005;
Edge edge[maxm];
int dis[maxn];
int n,m;
int source;
bool bellmanford(){
int i;
int j;
for(i = 1 ; i <= n ; ++i){
dis[i] = inf;
}
dis[source] = 0;
for(i = 1 ; i <= n ; ++i){
for(j = 1 ; j <= m ; ++j){
if(dis[edge[j].v] > dis[edge[j].u] + edge[j].weight){
dis[edge[j].v] = dis[edge[j].u] + edge[j].weight;
}
if(dis[edge[j].u] > dis[edge[j].v] + edge[j].weight){
dis[edge[j].u] = dis[edge[j].v] + edge[j].weight;
}
}
}
for(j = 1 ; j <= m ; ++j){
if(dis[edge[j].v] > dis[edge[j].u] + edge[j].weight){
return false;
}
}
return true;
}
int main(){
while(scanf("%d%d",&n,&m),n||m){
int i;
for(i = 1 ; i <= m ; ++i){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].weight);
}
source = 1;
bellmanford();
printf("%d\n",dis[n]);
}
return 0;
}
2、HDU 2066 一个人的旅行
题目分析:
这一道题还是最短路径问题。但是有以下几个不同点:
1》与平常的给出点数、边数、起点、终点不同。这道题给出了多个起点和终点、并且没有给出点数
这道题我用floyd做的时候TLE了,所以暂时只给出dijkstra解法的版本
/*
* HDU_2066.cpp
*
* Created on: 2014年6月1日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1010;
const int inf = 100000005;
int s[1015];
int dis[1015];
int map[1015][1015];
int start, d;
int from[maxn];
int want[maxn];
int dijkstra(int v) {
int i;
for (i = 1; i <= maxn; ++i) {//因为题目没有给出点数,所以每一次都全部扫一遍
s[i] = false;
dis[i] = map[v][i];
}
for (i = 1; i < maxn; ++i) {
int min = inf;
int pos;
int j;
for (j = 1; j <= maxn; ++j) {
if (!s[j] && dis[j] < min) {
min = dis[j];
pos = j;
}
}
s[pos] = 1;
for (j = 1; j <= maxn; ++j) {
if (!s[j] && dis[j] > dis[pos] + map[pos][j]) {
dis[j] = dis[pos] + map[pos][j];
}
}
}
//到这里就已经算出以点v为起点的最短路径的情况了....这时候再遍历一下ends[],便能求出v到ends[]中哪个终点最近了
int minn = inf;
for (i = 0; i < d; ++i) {//用来解决多终点的问题
int temp = dis[want[i]];
if (minn > temp) {
minn = temp;
}
}
return minn;
}
int main() {
int t;
while (scanf("%d%d%d", &t, &start, &d) != EOF) {
int i;
int j;
for (i = 1; i <= maxn; ++i) {
for (j = 1; j <= maxn; ++j) {
if (i == j) {
map[i][j] = map[j][i] = 0;
} else {
map[i][j] = map[j][i] = inf;
}
}
}
for (i = 1; i <= t; ++i) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (map[a][b] > c) {
map[a][b] = map[b][a] = c;
}
}
for (i = 0; i < start; ++i) {
scanf("%d", &from[i]);
}
for (i = 0; i < d; ++i) {
scanf("%d", &want[i]);
}
int result = inf;
for (i = 0; i < start; ++i) {//用来解决多起点的问题
int temp = dijkstra(from[i]);
if (result > temp) {
result = temp;
}
}
printf("%d\n", result);
}
return 0;
}