您的位置:首页 > 其它

NOJ1049飞机最少换乘次数问题——BFS

2014-06-11 18:16 239 查看

飞机最少换乘次数问题

Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByte

Total Submit:379 Accepted:157

Description

设有n个城市,编号为0~n-1,m条单向航线的起点和终点由输入提供,寻找一条换乘次数最少的线路方案。

Input
第一行为三个整数n、m、v,表示城市数、单向航线数和起点城市。以下m行每行两个整数,表示一条边的起点、终点,保证不重复、不失败。2≤n≤20,1≤m≤190

Output
共n-1行,分别是从起点城市v到其他n-1个城市最少换乘次数,按照终点城市序号从小到大顺序输出,不能抵达时输出-1。

Sample Input
3 2 0

0 1

1 2
Sample Output
1

2

Source
CHENZ

分析:此题是宽度优先遍历的一个应用。
要求最少换乘次数,显然由于BFS就是按宽度,类似二叉树中的深度遍历的。关键在于问题的转化和细节。
引入int ans[]; 保存点v到i的最少换乘次数。下标即为i。
用len表示最小换乘次数。
len是由点first决定的,即点first能到达的点(可能有一些点)它们的 最小换乘次数 都是 first这个的len + 1。所以len ++;的位置很关键。一开始我写在

if(tag[i] == 0 && a[first][i] == 1) // 去掉v
{
myList.push_back(i);
tag[i] = 1;
ans[i] = len; // v到i的最少换乘次数
}
这个循环的里面了。哎哟~Test 1和Test 2还是对的,但是Test 3就错了。原因可能前2个测试数据数组没有1个点直接相连多个点的情况。

注意点:航向是单向的,所以与之前的无向图不一样。
输出的不需要自己到自己。
不能抵达时输出-1。所以ans数组一定要初始化。

#include<iostream>
#include<string>
#include<list>
using namespace std;

list<int> myList;
int a[20][20];
int tag[20]; // 0-未被访问过
int ans[20]; // 需要求的答案
int n; // 全局变量,BFS函数中要用

void BFS(int v)
{
int len = 1; // 最少换乘次数
myList.push_back(v);
tag[v] = 1;
while(myList.size() > 0)
{
int first = myList.front();
myList.pop_front();
for(int i=0;i<n;i++)
{
if(tag[i] == 0 && a[first][i] == 1) // 去掉v { myList.push_back(i); tag[i] = 1; ans[i] = len; // v到i的最少换乘次数 }
}
len ++; // !!!
}
}

int main()
{
memset(a, 0, sizeof(a));
memset(tag, 0, sizeof(tag));
memset(ans, -1, sizeof(ans)); // !!!不能抵达时输出-1
int m, v, x, y;
scanf("%d%d%d",&n,&m,&v);
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
a[x][y] = 1;
//a[y][x] = 1; // 单向!!!
}
BFS(v);
for(int i=0;i<n;i++)
{
if(i != v) // 不包括自己
printf("%d\n",ans[i]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: