D:圆
正着求删除的最小代价不好做,采用逆向思维,求选择一些不相交的线段使得构成一个圆的代价尽量大,最后答案就是所有线段权值之和减去最大代价。
那么如何求这个最大代价呢?显然区间DP
老套路:破环成链,枚举区间长度 len ,枚举区间左端点 i 和右端点 j
很明显没有线段长度为1,故len从2开始
具体的
线段的操作和点的相似但又不完全相同具体看代码即可。
1:不选择以左端点的线段,
2、选择以为左端点的线段。枚举左端点 所能到达的右端点 v,权值为 w,那么当前的答案
由 区间 的答案加上 区间 的答案加上线段 的权值构成,即
int n, m;
int f[M][M]; // f[i][j] 区间i到j不相交边的最大价值
vector<PII> g[N];
void solve()
{
cin >> n >> m;
int s = 0;
for (int i = 1; i <= m; i++)
{
int x, y, w;
cin >> x >> y >> w;
if (x > y)
swap(x, y);
g[x].pb({y, w});
g[y].pb({x + n, w});
s += w;
}
for (int len = 2; len <= 2 * n; len++)
{
for (int i = 1; i + len - 1 <= 2 * n; i++)
{
int j = i + len - 1;
f[i][j] = f[i + 1][j]; // 不选择以i为左端点的线段
for (auto ed : g[i]) // 选择以i为左端点的线段
{
int v = ed.xx, w = ed.yy;
if (v > j) // 已经越过右端点了
continue;
if (v - 1 > i + 1) //
w += f[i + 1][v - 1];
if (j > v + 1)
w += f[v + 1][j];
f[i][j] = max(f[i][j], w);
}
}
}
int tmp = 0;
for (int i = 1; i <= n; i++)
tmp = max(tmp, f[i][i + n - 1]);
s = s - tmp;
cout << s << endl;
}