版权声明:欢迎借鉴,谢绝抄搬。 https://blog.csdn.net/Gx_Man_VIP/article/details/88782081
题目大意:
给出 个点 个单向边,问任选4个点(各不相同)构成的路径A->B->C->D,使得点点间最短路径之和最大时的选点方案是什么。
分析:
所有的边长度均为 ,那么我们令 表示 到 的最短距离,然后队列中加入 ( ),每次往相邻的点跑,先到达的肯定就是最短的。
然后我们对于一个路径
,可以发现
肯定是到
中最大的或者次大的,
肯定是
能到中最大的或者次大的,
那么预处理,
令
表示到第
个点最短距离中最大的点和次大的点,
令
表示第
个点能到的其他点的最短距离最大的和次大的是哪个。
然后枚举
,
利用预处理的
去找即可
时间复杂度:
代码:
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 3005
#define M 5005
using namespace std;
struct Node{int To, nxt; }e[M];
int maxFrom[N][2], maxTo[N][2], dis[N][N], ls[N], cnt, n, m;
queue <int> Q[2];
void Addedge(int u, int v)
{
e[++cnt].To = v, e[cnt].nxt = ls[u], ls[u] = cnt;
}
void spfa()
{
memset(dis, 255, sizeof(dis));
for (int i = 1; i <= n; i++)
dis[i][i] = 0, Q[0].push(i), Q[1].push(i);
while (Q[0].size())
{
int now = Q[0].front(); Q[0].pop();
int u = Q[1].front(); Q[1].pop();
for (int i = ls[u]; i; i = e[i].nxt)
if (dis[now][e[i].To] == -1)
{
dis[now][e[i].To] = dis[now][u] + 1;
Q[0].push(now), Q[1].push(e[i].To);
}
}
}
bool check(int a, int b, int c, int d)
{
if (a == b || a == c || a == d || d == b || d == c) return 0;
return 1;
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d %d", &u, &v);
Addedge(u, v);
}
spfa();
for (int i = 1; i <= n; i++)
{
maxTo[i][1] = maxTo[i][0] = maxFrom[i][1] = maxFrom[i][0] = i;
for (int j = 1; j <= n; j++)
{
if (dis[i][j] > dis[i][maxTo[i][0]]) maxTo[i][1] = maxTo[i][0], maxTo[i][0] = j;
else if (dis[i][j] > dis[i][maxTo[i][1]]) maxTo[i][1] = j;
if (dis[j][i] > dis[maxFrom[i][0]][i]) maxFrom[i][1] = maxFrom[i][0], maxFrom[i][0] = j;
else if (dis[j][i] > dis[maxFrom[i][1]][i]) maxFrom[i][1] = j;
}
}
int Answer = -1, A, B, C, D;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j && dis[i][j] != -1)
for (int rk1 = 0; rk1 <= 1; rk1++)
for (int rk2 = 0; rk2 <= 1; rk2++)
{
int begind = maxFrom[i][rk1], endd = maxTo[j][rk2];
if (check(begind, i, j, endd) && dis[begind][i] + dis[i][j] + dis[j][endd] > Answer)
Answer = dis[begind][i] + dis[i][j] + dis[j][endd], A = begind, B = i, C = j, D = endd;
}
printf("%d %d %d %d\n", A, B, C, D);
return 0;
}