这题是真TM复杂。。。感觉考试的时候绝对做不出来。。。dijsktra的算法还是要再熟悉熟悉。。。基础真的还是太差。。。
其实就是两次dij,然后要记住路径,我用了pre[501]来存储前一个节点,最后再倒着走回来,不知道这么写是不是有点复杂了。。。
#include<iostream> #include<string> #include<map> #include<vector> #include<algorithm> #include<queue> #include<set> #include<stack> using namespace std; const int INF = 99999999; int tim[501][501]; int length[501][501]; int n, m; int s, d; int t[501]; int l[501]; int inter[501]; int pre[501]; int vist[501]; void dij() { for (int i = 0; i < n; i++) { int u = -1; int MIN = INF; for (int j = 0; j < n; j++) { if (vist[j] == 0 && MIN > t[j]) { u = j; MIN = t[j]; } } if (u == -1) break; vist[u] = 1; for (int v = 0; v < n; v++) { if (vist[v] == 0 && tim[u][v] != INF) { if (t[u] + tim[u][v] < t[v]) { t[v] = t[u] + tim[u][v]; inter[v] = inter[u] + 1; pre[v] = u; } else if (t[u] + tim[u][v] == t[v] && inter[v] > inter[u] + 1) { t[v] = t[u] + tim[u][v]; inter[v] = inter[u] + 1; pre[v] = u; } } } } } void dij2() { for (int i = 0; i < n; i++) { int u = -1; int MIN = INF; for (int j = 0; j < n; j++) { if (vist[j] == 0 && MIN > l[j]) { u = j; MIN = l[j]; } } if (u == -1) break; vist[u] = 1; for (int v = 0; v < n; v++) { if (vist[v] == 0 && length[u][v] != INF) { if (l[u] + length[u][v] < l[v]) { l[v] = l[u] + length[u][v]; t[v] = t[u] + tim[u][v]; pre[v] = u; } else if (t[u] + tim[u][v] < t[v] && l[u] + length[u][v] == l[v]) { l[v] = l[u] + length[u][v]; t[v] = t[u] + tim[u][v]; pre[v] = u; } } } } } int main() { cin >> n >> m; fill(tim[0], tim[0] + (501 * 501), INF); fill(length[0], length[0] + (501 * 501), INF); for (int i = 0; i < m; i++) { int t1, t2, ow, t, l; cin >> t1 >> t2 >> ow >> l >> t; if (ow == 0) { tim[t1][t2] = tim[t2][t1] = t; length[t1][t2] = length[t2][t1] = l; } else { tim[t1][t2] = t; length[t1][t2] = l; } } cin >> s >> d; fill(t, t + 501, INF); t[s] = 0; fill(vist, vist + 501, 0); dij(); int z = d; int totalt = 0; vector<int> p1; vector<int> p2; while (z != s) { p1.push_back(z); totalt += tim[pre[z]][z]; z = pre[z]; } reverse(p1.begin(), p1.end()); fill(vist, vist + 501, 0); fill(pre, pre + 501, 0); fill(t, t + 501, INF); fill(l, l + 501, INF); l[s] = 0; dij2(); int totald = 0; z = d; while (z != s) { p2.push_back(z); totald += length[pre[z]][z]; z = pre[z]; } reverse(p2.begin(), p2.end()); if (p1 != p2) { printf("Distance = %d: ", totald); printf("%d", s); for (int i = 0; i < p2.size(); i++) { printf(" -> %d", p2[i]); } cout << endl; printf("Time = %d: ", totalt); printf("%d", s); for (int i = 0; i < p1.size(); i++) { printf(" -> %d", p1[i]); } } else { printf("Distance = %d; ", totald); printf("Time = %d: ", totalt); printf("%d", s); for (int i = 0; i < p1.size(); i++) { printf(" -> %d", p1[i]); } } system("pause"); }