专栏文章
P11676 [USACO25JAN] DFS Order P
P11676题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqchtyw
- 此快照首次捕获于
- 2025/12/04 02:33 3 个月前
- 此快照最后确认于
- 2025/12/04 02:33 3 个月前
P11676 [USACO25JAN] DFS Order P
题意:
有一个 个点的无向图和一个 的矩阵 , 说明这条边当前不在,加入的代价是 , 说明这条边当前在,删除的代价是 。
可以增删一些边,使得存在一个 dfs 序是 。
。
思路:
这个数据范围不是网络流就是 dp,经过尝试会发现网络流不太好做,考虑 dp。
如果我们当前搜到了 ,则我们要求除了走过来的这条边, 不能和前面的点有任何连边。
我们考虑区间 dp:设 表示进入 的子树中,最后一个搜完的是 。
首先,有 的代价,因为如果 之后 回溯了那么是不能和后面有边的。
我们先不考虑这个代价,我们类似树形 考虑一个子树一个子树的加入。
枚举一个 ,考虑能转移到哪些状态。
我们枚举下一个子树到 ,则转移就是:
这样就能 求出所有 ,总的时间复杂度就是 。
CPP#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 755;
const int inf = 0x3f3f3f3f;
int n;
int a[N][N] = {{0}};
int f[N][N] = {{0}}, g[N][N] = {{0}};
void cmn(int &x, int y) {
x = min(x, y);
}
int main() {
scanf("%d", &n);
for (int i = 2; i <= n; i++)
for (int j = 1; j < i; j++)
scanf("%d", &a[j][i]);
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++)
g[i][j] = max(0, -a[i][j]);
for (int j = n - 1; j >= i + 1; j--)
g[i][j] += g[i][j + 1];
}
memset(f, 0x3f, sizeof f);
for (int i = n; i >= 1; i--) {
f[i][i] = 0;
for (int j = i; j <= n; j++) {
if (f[i][j] != inf) {
for (int k = 1; j + k <= n; k++) {
cmn(f[i][j + k], f[i][j] + f[j + 1][j + k] + max(0, a[i][j + 1]));
}
}
}
for (int j = i; j <= n; j++)
f[i][j] += g[i][j + 1];
}
cout << f[1][n] << endl;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...