WhiteThe Snow in Village

[CSP-S 2022] 假期计划

Spaceswalker-2023-10-14 18:26-123 has reading

[CSP-S 2022] 假期计划

[CSP-S 2022] 假期计划

题目传送门

题目大意#

给定一个 n2500,m10000 的无向图,有点权。求一条点权和最大的路径 1ABCD1,满足:

  • A,B,C,D 均不为 1,且互不相同;
  • 每一段路径上经过的点的数量小于等于 k
  • 题目分析#

    不难想到要通过 bfs 预处理出任意两点间距离。

    然后就可以写出一个 O(nm+n4) 暴力了:直接枚举 A,B,C,D 并判断是否合法。

    此时注意到 n2.5×103,也就是说:我们至多可以枚举两个点。

    于是我们折半一下,预处理对于每个 B,所有 A(即 1AB)的最大、次大、次次大的值,求值时枚举 B,C 并统计即可。

    时间复杂度为 O(n(n+m))

    代码实现#

    Copy
    #include <bits/stdc++.h> #define rint register int #define endl '\n' #define int long long using namespace std; const int N = 2.5e3 + 5; const int M = 2e5 + 5; const int inf = 1e18; int n, m, k; int ans; int h[M], e[M], ne[M], idx; int dist[N][N], f[N][N], pos[N][3]; int s[N]; queue<int> q; void add(int a, int b) { e[++idx] = b, ne[idx] = h[a], h[a] = idx; } void init(int n) { for (rint i = 1; i <= n; i++) { for (rint j = 1; j <= n; j++) { dist[i][j] = inf; } } } void bfs(int s) { dist[s][s] = 0; q.push(s); while(!q.empty()) { int x = q.front(); q.pop(); for (rint i = h[x]; i; i = ne[i]) { int y = e[i]; if (dist[s][y] == inf) { dist[s][y] = dist[s][x] + 1; q.push(y); } } } } signed main() { cin >> n >> m >> k; k += 1; init(n); for (rint i = 2; i <= n; i++) { cin >> s[i]; } for (rint i = 1; i <= m; i++) { int a, b; cin >> a >> b; add(a, b); add(b, a); } for (rint i = 1; i <= n; i++) { bfs(i); } for (rint i = 1; i <= n; i++) { for (rint j = 1; j <= n; j++) { if (i != j && dist[1][i] <= k && dist[i][j] <= k) { f[i][j] = s[i] + s[j]; } else { f[i][j] = -inf; } } } for (rint i = 2; i <= n; i++) { pos[i][1] = i; pos[i][2] = i; pos[i][3] = i; for (rint j = 2; j <= n; j++) { if (f[pos[i][1]][i] < f[j][i]) { pos[i][3] = pos[i][2]; pos[i][2] = pos[i][1]; pos[i][1] = j; } else if (f[pos[i][2]][i] < f[j][i]) { pos[i][3] = pos[i][2]; pos[i][2] = j; } else if (f[pos[i][3]][i] < f[j][i]) { pos[i][3] = j; } } } for (rint i = 2; i <= n; i++) { for (rint j = 2; j <= n; j++) { if (i != j && dist[i][j] <= k) { for (rint x = 1; x <= 3; x++) { for (rint y = 1; y <= 3; y++) { if (pos[i][x] != j && pos[i][x] != pos[j][y] && pos[j][y] != i) { ans = max(ans, f[pos[i][x]][i] + f[pos[j][y]][j]); break; } } } } } } cout << ans << endl; return 0; }
posted @   南松的科技树  阅读(123)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示
Reading Sub
?