最少转机---图的广度优先遍历
摘自《啊哈算法》:小哼和小哈一同坐飞机去旅游,他们现在位于1号城市,目标是5号城市,可是1号城市并没有直接到5号城市的直航. 不过小哼已经收集到了很多航班的信息,现在小哼希望找到一中乘坐方式,使得转机的次数最少?
输入数据样式为:
5 7 1 5
1 2
1 3
2 3
2 4
3 4
3 5
4 5
第一行:5表示有5个城市;7表示有7条航线;1表示起点城市;5表示目标城市
接下来7行每行是一条类似“a b”这样的数据表示城市a和城市b之间有航线,可以互相到达。
完整代码如下
#include <stdio.h> #include <string.h> #include <stdlib.h> #define INF 999999 struct note { int x; // 城市编号 int s; // 转机次数 }; int book[100]; int main(int argc, char const *argv[]) { int i, j, m, n, cur; int a, b, e[101][101]; int head, tail; int start, end; int flag = 0; struct note que[2501]; scanf_s("%d %d %d %d", &n, &m, &start, &end); //初始化二维矩阵 for (i = 1; i <= n; ++i) { for (j = 1; j <= n; ++j) { if (i == j) { e[i][j] = 0; } else { e[i][j] = INF; } } } //读入城市之间的航班 for (i = 1; i <= m; ++i) { scanf_s("%d %d", &a, &b); //注意这里是无向图 e[a][b] = 1; e[b][a] = 1; } //队列初始化 head = 1; tail = 1; //从start号城市出发,将start号城市加入队列 que[tail].x = start; que[tail].s = 0; tail++; book[start] = 1;//标记start号城市已经在队列中 //当队列不为空时循环 while (head < tail) { cur = que[head].x;//当前队列中首城市的编号 for (i = 1; i <= n; ++i) //从1到n依次尝试 { //从城市cur到城市i是否有航班且判断城市i是否在队列中 if (e[cur][i] == 1 && book[i] == 0) { //不在队列中,入队 que[tail].x = i; que[tail].s = que[head].s + 1;//转机次数加1 tail++; //标记城市i已经在队列中 book[i] = 1; } if (que[tail - 1].x == end) //达到目标城市, 退出循环 { flag = 1; break; } } if (flag==1) { break; } head++; //有head++,才能继续扩展 } //打印队列中末尾最后一个(目标城市)的转机次数 //注意tail是指向队列队尾的下一个位置,所以这里需要减1 printf("从%d城市转机到%d城市的最少转机次数是:\n", start, end); printf("%d\n", que[tail - 1].s); system("pause"); return 0; }
结果如下: