题意
给出一张图,上面有若干点相连,且边权都为1,求出4个点使得它们不重复,并且遍历它们的总路径长度最大,每次遍历都只会走两点之间的最短路。
思路
求出两点之间的最短路,之后用记忆化搜索找出答案。
代码
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
int n, m, tot, ansum;
int edge[5001], next[5001], ver[5001], head[5001], v[5001], dis[3001][3001], f[3001][5], ans[5], st[5];
void bfs(int s) {
std::queue<int> q;
memset(v, 0, sizeof(v));
v[s] = 1;
q.push(s);
while (q.size()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = next[i]) {
int y = ver[i];
if (v[y]) continue;
dis[s][y] = dis[s][x] + 1;
q.push(y);
v[y] = 1;
}
}
}
void dfs(int p, int sum, int num) {
if (sum < f[p][num]) return;
f[p][num] = sum;//f[p][sum]记录当前p点选了num个点时的最长路径
st[num] = p;
if (num == 4) {
if (sum <= ansum) return;
ansum = sum;
for (int i = 1; i <= 4; i++)
ans[i] = st[i];
return;
}
for (int i = 1; i <= n; i++) {
if (!dis[p][i]) continue;
int f = 0;
for (int j = 1; j <= num; j++)
if (st[j] == i) {
f = 1;
break;
}
if (f) continue;
dfs(i, sum + dis[p][i], num + 1);
}
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
int x, y;
scanf("%d %d", &x, &y);
edge[++tot] = 1;
ver[tot] = y;
next[tot] = head[x];
head[x] = tot;
}
for (int i = 1; i <= n; i++)
bfs(i);
for (int i = 1; i <= n; i++) {
memset(st, 0, sizeof(st));
dfs(i, 0, 1);
}
for (int i = 1; i <= 4; i++)
printf("%d ", ans[i]);
}