P11676 DFS Order 题解
sunkuangzheng · · 题解
给定一张
n(1 \le n \le 750) 个点的无向图,可以花费a_{i,j}(a_{i,j} \ge 0) 的代价修改边(i,j) 的存在状态,求让[1,2,\ldots,n] 变成原图一个 DFS 序的最小代价。
首先考虑原图里没有边的部分分,此时最后图的形态一定是一棵树。
注意到 dfs 树的结构是很好的,一个子树内的点集一定是一个连续区间,且没有向外连边。每个子树内部的决策实际上是独立的。令
考虑现在原图有一些边,我们可以直接将它们全删除,然后将加这条边的代价改成
/**
* author: sunkuangzheng
* created: 28.01.2025 13:37:41
**/
#include<bits/stdc++.h>
#ifdef DEBUG_LOCAL
#include <mydebug/debug.h>
#endif
using ll = long long;
const int N = 751;
using namespace std;
int T,n,a[N][N],f[N][N],sm[N][N];
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin >> n; int c = 0;
for(int j = 2;j <= n;j ++) for(int i = 1;i < j;i ++) cin >> a[i][j],
c += a[i][j] < 0 ? -a[i][j] : 0;
for(int i = 1;i <= n;i ++) f[i][i] = 0;
for(int i = 1;i <= n;i ++) for(int j = i + 1;j <= n;j ++)
sm[i][j] = sm[i][j-1] + (a[i][j] < 0 ? a[i][j] : 0);
for(int l = 2;l <= n;l ++) for(int i = 1;i + l - 1 <= n;i ++){
int j = i + l - 1; f[i][j] = 1e9;
for(int k = i;k < j;k ++)
f[i][j] = min(f[i][j],f[i][k] + f[k + 1][j] + sm[i][j] - sm[i][k+1] + a[i][k+1]);
}cout << f[1][n] + c << "\n";
}