1131 Subway Map (30 分)
题目大意:
给我们地铁的路线,交我们求两个地铁站的最短路径,如果路径相同,则选择那个经过公交站最少的路线
思路:
要我们输出路径,所以必须要存取路径,而且要存取路径的颜色,所以最好的存图方法就是向前星,可以存边,把边标注上颜色
每两点的长度都是相同的,所以最容易想到用bfs求最短路径,用常用的pre数组存储前驱,但是这次是存到达的边,不是点,
但是直接用bfs求出来的结果还是不能完全通过,因为选择经过公交站最少的路线无法保障,所以改进算法思路,先用bfs求最短路径
再用dfs选择长度为最短路径的所有路径中最优的那个,算是一个比较综合的题,虽然我没试过直接dfs,但是应该会超时.不然我就白想这么久了=-=.
代码:
#include<iostream> #include<queue> #include<string.h> #include<string> #include<map> #include<unordered_map> #include<vector> #include<algorithm> #include<cmath> #include<set> using namespace std; const int maxn = 1e5 + 1; const int maxm = 1e6 + 1; #define INT_MAX 0x7777777 typedef long long ll; inline int read() { int X = 0; bool flag = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-') flag = 0; ch = getchar(); } while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar(); } if (flag) return X; return ~(X - 1); } struct edge { int f,to, nxt, col; }e[maxm]; int hd[maxn], tot; void add(int f, int t, int col) { e[++tot] = { f,t,hd[f],col }; hd[f] = tot; } edge pre[maxn]; bool vis[maxn]; int n; int bfs(int st, int ed) { queue<int>Q; Q.push(st); vis[st] = 1; int len = 0; while (!Q.empty()) { int size = Q.size(); for (int i = 0; i < size; i++) { int t = Q.front(); Q.pop(); for (int now = hd[t]; now; now = e[now].nxt) { int v = e[now].to; if (!vis[v]) { vis[v] = 1; Q.push(v); } } } len++; if (vis[ed])return len; } } vector<edge>res; int ans; int s; void dfs(int len, int st, int ed,int colnum,int precol) { //colnum,到达st需要经过的线路个数,precol,上一次经过的线路,用来判断是否colnum要+1 if (len == 0) { if (st == ed && ans > colnum){//跟新最优解 ans = colnum; res.clear(); int p = ed; while (pre[p].f != s) { res.push_back(pre[p]); p = pre[p].f; } res.push_back(pre[p]); } return; } vis[st] = 1; for (int i = hd[st]; i; i = e[i].nxt) { int v = e[i].to; if (!vis[v]) { pre[v] = e[i]; if (e[i].col != precol)colnum += 1; dfs(len - 1, v, ed, colnum, e[i].col); } } vis[st] = 0; } void print() {//按照题目要求打印路径 int i = res.size() - 1; printf("%d\n", res.size()); while (i >= 0) { int st = res[i].f, ed=res[i].to, col = res[i].col; i -= 1; while (i >= 0 && col == res[i].col){ ed = res[i].to; i--; } printf("Take Line#%d from %04d to %04d.\n", col, st, ed); } } int main() { //freopen("test.txt", "r", stdin); n = read(); for (int i = 1; i <= n; i++) { int k = read(); int f = read(),t; for (int j = 2; j <= k; j++) { t = read(); add(f, t,i); add(t, f,i);//加边以及边得颜色 f = t; } } int k = read(); while (k--) { int a = read(), b = read(); memset(vis, 0, sizeof(vis)); int len=bfs(a,b); memset(vis, 0, sizeof(vis)); ans = INT_MAX; s = a; dfs(len, a, b,0,-1); print(); } return 0; }