有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求这些牛中所花的最长的来回时间是多少。
每头牛返回的最短时间很简单就可以算出来,这相当于从目标牛为起点求单源最短路径。但每头牛出发到目标牛的最短时间无法直接算出来,稍微转换一下,发现这个最短时间其实可以通过把所有的边取反向,然后再从目标牛求一次单源最短路径得到。得到这两个最短路径之后,取它们的和的最大者即可。
邻接阵O(n^2):
#include <iostream> #include <cstdio> #include <algorithm> #include <climits> using namespace std; const int N = 1005; int edge[N][N]; int n, e, x; int mindis1[N]; int mindis2[N]; bool vis1[N]; bool vis2[N]; void init() { for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { edge[i][j] = -1; } } } void dijkstra(int s) { int pos1, pos2, te1, te2, tm1, tm2; for (int i = 0; i < n; ++i) { vis1[i] = false; vis2[i] = false; mindis1[i] = 999999; mindis2[i] = 999999; } mindis1[s] = 0; mindis2[s] = 0; vis1[s] = true; vis2[s] = true; pos1 = s; pos2 = s; for (int i = 0; i < n - 1; ++i) { for (int j = 0; j < n; ++j) { if (!vis1[j] && edge[pos1][j] != -1 && mindis1[pos1] + edge[pos1][j] < mindis1[j]) { mindis1[j] = mindis1[pos1] +edge[pos1][j]; } if (!vis2[j] && edge[j][pos2] != -1 && mindis2[pos2] + edge[j][pos2] < mindis2[j]) { mindis2[j] = mindis2[pos2] + edge[j][pos2]; } } tm1 = 999999; tm2 = 999999; for (int j = 0; j < n; ++j) { if (!vis1[j] && mindis1[j] < tm1) { tm1 = mindis1[j]; te1 = j; } if (!vis2[j] && mindis2[j] < tm2) { tm2 = mindis2[j]; te2 = j; } } vis1[te1] = true; pos1 = te1; vis2[te2] = true; pos2 = te2; } } int main() { int beg, end, dis; scanf("%d%d%d", &n, &e, &x); init(); for (int i = 0; i < e; ++i) { scanf("%d%d%d", &beg, &end, &dis); --beg; --end; edge[beg][end] = dis; } dijkstra(--x); int ans = 0; for (int i = 0; i < n; ++i) { if (i == x) continue; if (mindis1[i] + mindis2[i] > ans) ans = mindis1[i] + mindis2[i]; } printf("%d\n", ans); return 0; }
邻接表O(E*logE):
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int N = 1005; const int E = 1000005; struct Edge { int pnt; int dis; int next; }; Edge edge1[E], edge2[E]; int cur1, cur2; int neigh1[N], neigh2[N]; int n, e, x; int mindis1[N]; int mindis2[N]; bool vis1[N]; bool vis2[N]; struct Qnode { int pnt; int dis; Qnode(int _pnt, int _dis): pnt(_pnt), dis(_dis){} bool operator < (const Qnode& node) const { return dis > node.dis; } }; void addedge(int beg, int end, int dis) { edge1[cur1].pnt = end; edge1[cur1].dis = dis; edge1[cur1].next = neigh1[beg]; neigh1[beg] = cur1; ++cur1; edge2[cur2].pnt = beg; edge2[cur2].dis = dis; edge2[cur2].next = neigh2[end]; neigh2[end] = cur2; ++cur2; } void dijkstra(int s) { int pre1, pre2, te1, te2, pnt1, pnt2; priority_queue<Qnode> pq1, pq2; for (int i = 0; i < n; ++i) { vis1[i] = false; vis2[i] = false; mindis1[i] = 999999; mindis2[i] = 999999; } mindis1[s] = 0; mindis2[s] = 0; vis1[s] = true; vis2[s] = true; pq1.push(Qnode(s, 0)); pq2.push(Qnode(s, 0)); pre1 = s; pre2 = s; for (int i = 0; i < n - 1; ++i) { te1 = neigh1[pre1]; while (te1 != -1) { pnt1 = edge1[te1].pnt; if (!vis1[pnt1] && mindis1[pre1] + edge1[te1].dis < mindis1[pnt1]) { mindis1[pnt1] = mindis1[pre1] + edge1[te1].dis; pq1.push(Qnode(pnt1, mindis1[pnt1])); } te1 = edge1[te1].next; } while (!pq1.empty() && vis1[pq1.top().pnt]) pq1.pop(); pre1 = pq1.top().pnt; vis1[pre1] = true; pq1.pop(); te2 = neigh2[pre2]; while (te2 != -1) { pnt2 = edge2[te2].pnt; if (!vis2[pnt2] && mindis2[pre2] + edge2[te2].dis < mindis2[pnt2]) { mindis2[pnt2] = mindis2[pre2] + edge2[te2].dis; pq2.push(Qnode(pnt2, mindis2[pnt2])); } te2 = edge2[te2].next; } while (!pq2.empty() && vis2[pq2.top().pnt]) pq2.pop(); pre2 = pq2.top().pnt; vis2[pre2] = true; pq2.pop(); } } int main() { int beg, end, dis; scanf("%d%d%d", &n, &e, &x); for (int i = 0; i < n; ++i) { neigh1[i] = -1; neigh2[i] = -1; } cur1 = cur2 = 0; for (int i = 0; i < e; ++i) { scanf("%d%d%d", &beg, &end, &dis); --beg; --end; addedge(beg, end, dis); } dijkstra(--x); int ans = 0; for (int i = 0; i < n; ++i) { if (i == x) continue; if (mindis1[i] + mindis2[i] > ans) ans = mindis1[i] + mindis2[i]; } printf("%d\n", ans); return 0; }