有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求这些牛中所花的最长的来回时间是多少。
每头牛返回的最短时间很简单就可以算出来,这相当于从目标牛为起点求单源最短路径。但每头牛出发到目标牛的最短时间无法直接算出来,稍微转换一下,发现这个最短时间其实可以通过把所有的边取反向,然后再从目标牛求一次单源最短路径得到。得到这两个最短路径之后,取它们的和的最大者即可。
邻接阵O(n^2):
#include
#include
#include
#include
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
#include
#include
#include
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 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;
}