题目链接
http://poj.org/problem?id=1847
题意
有n个车站,编号1~n,每个车站有k个出口,车站的出口默认是k个出口中的第一个,如果不想从默认出口出站,则需要手动选择出站口。现在从车站a出发,求最少需要手动选择几次出站口才能到车站b。
思路
这题的图中没有显式给出结点之间的距离,但可以根据题意给路径添加距离,比如测试数据中的“2 2 3”表示从第1个车站默认开往第2个车站,想要开到第3个车站则需手动选择,所以我们可以令结点1到结点2的边权值为0(默认车站),结点1到结点3边权值为1(需手动选择的车站),这样就可以使用Dijkstra算法、Floyd算法或者SPFA算法求解a,b之间的最短路,a,b之间最短路的值即是需手动选择车站的次数。
代码
Dijkstra算法和Floyd算法:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int INF = 0x3f3f3f; 8 const int N = 100 + 10; 9 int map[N][N]; 10 int dist[N]; 11 int visit[N]; 12 int n, a, b; 13 14 void dijkstra() //Dijkstra算法 15 { 16 memset(visit, 0, sizeof(visit)); 17 for (int i = 1; i <= n; i++) 18 dist[i] = map[a][i]; 19 dist[a] = 0; 20 visit[a] = 1; 21 int min_dist, now = a; 22 for (int i = 1; i <= n; i++) 23 { 24 min_dist = INF; 25 for (int j = 1; j <= n; j++) 26 { 27 if (!visit[j] && dist[j] < min_dist) 28 { 29 min_dist = dist[j]; 30 now = j; 31 } 32 } 33 visit[now] = 1; 34 for (int j = 1; j <= n; j++) 35 dist[j] = min(dist[j], dist[now] + map[now][j]); 36 } 37 if (dist[b] >= INF) //注意是dist[b]>=INF,不是dist[b]==INF 38 puts("-1"); 39 else printf("%d ", dist[b]); 40 } 41 42 void floyd() //Floyd算法 43 { 44 for (int k = 1; k <= n; k++) 45 for (int i = 1; i <= n; i++) 46 for (int j = 1; j <= n; j++) 47 map[i][j] = min(map[i][j], map[i][k] + map[k][j]); 48 if (map[a][b] >= INF) 49 puts("-1"); 50 else printf("%d ", map[a][b]); 51 } 52 53 int main() 54 { 55 //freopen("poj1847.txt", "r", stdin); 56 while (scanf("%d%d%d", &n, &a, &b) == 3) 57 { 58 memset(map, INF, sizeof(map)); 59 int k, t; 60 for (int i = 1; i <= n; i++) 61 { 62 scanf("%d", &k); 63 for (int j = 1; j <= k; j++) 64 { 65 scanf("%d", &t); 66 if (j == 1) 67 map[i][t] = 0; 68 else map[i][t] = 1; 69 } 70 } 71 dijkstra(); 72 //floyd(); 73 } 74 return 0; 75 }
SPFA算法:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <vector> 6 #include <queue> 7 using namespace std; 8 9 struct Edge 10 { 11 int s, e, dist; 12 13 Edge() {} 14 Edge(int s, int e, int d) :s(s), e(e), dist(d) {} 15 }; 16 17 const int INF = 0x3f3f3f; 18 const int N = 100 + 10; 19 vector<Edge> v[N]; 20 int dist[N]; 21 int visit[N]; 22 int n, a, b; 23 24 void spfa(int s) 25 { 26 queue<int> q; 27 memset(dist, INF, sizeof(dist)); 28 memset(visit, 0, sizeof(visit)); 29 q.push(s); 30 visit[s] = 1; 31 dist[s] = 0; 32 33 while (!q.empty()) 34 { 35 int s = q.front(); 36 q.pop(); 37 visit[s] = 0; 38 for (int i = 0; i < v[s].size(); i++) 39 { 40 int e = v[s][i].e; 41 if (dist[e] > dist[s] + v[s][i].dist) 42 { 43 dist[e] = dist[s] + v[s][i].dist; 44 if (!visit[e]) 45 { 46 visit[e] = 1; 47 q.push(e); 48 } 49 } 50 } 51 } 52 if (dist[b] >= INF) 53 puts("-1"); 54 else printf("%d ", dist[b]); 55 } 56 57 int main() 58 { 59 //freopen("poj1847.txt", "r", stdin); 60 while (scanf("%d%d%d", &n, &a, &b) == 3) 61 { 62 for (int i = 1; i <= n; i++) 63 v[i].clear(); 64 65 int k, t; 66 for (int i = 1; i <= n; i++) 67 { 68 scanf("%d", &k); 69 for (int j = 1; j <= k; j++) 70 { 71 scanf("%d", &t); 72 if (j == 1) 73 v[i].push_back(Edge(i, t, 0)); 74 else v[i].push_back(Edge(i, t, 1)); 75 } 76 } 77 spfa(a); //求结点a到其余各点的最短路径 78 } 79 return 0; 80 }