@description@

给定一个 N 个点的有向带权图,从 0 编号到 N - 1。一开始这张图有 N - 1 条边,第 i 条边连接点 i 与点 i+1,边权为 0。

接着往这张图加边:对于每一对 (i, j)(i ≠ j),连 i -> j,当 i < j 时边权为 -1;否则边权为 1。

我们想要删掉一些边 (i, j)(i ≠ j),使得这张图不存在负环。删掉边 (i, j) 的费用为 A(i, j)。

请找到最小的删边费用,使得图中不存在负环。只能删之后加的边。

Constraints

3≤N≤500

1≤A(i, j)≤10^9

所有数都为整数。

Input

输入的格式如下:

N

A0,1 A0,2 A0,3 ⋯ A0,N−1

A1,0 A1,2 A1,3 ⋯ A1,N−1

A2,0 A2,1 A2,3 ⋯ A2,N−1



AN−1,0 AN−1,1 AN−1,2 ⋯ AN−1,N−2

Output

输出最小的删边费用。

Sample Input 1

3

2 1

1 4

3 3

Sample Output 1

2

Sample Input 2

4

1 1 1

1 1 1

1 1 1

1 1 1

Sample Output 2

2

@solution@

“感觉就是凑巧想到了这个做法,觉得有点道理于是逆向出了一道题。”——By lsk。

如果没有负环,意味着最短路存在。我们就从最短路出发来思考。

最短路有一个很经典的结论:三角形不等式。即对于任意一条边权为 w 的边 (u, v) 始终有 dis[u] + w >= dis[v]。

因此我们再从三角形不等式出发,进一步剖析这道题。

令最终的图中 0 号点到第 i 个点的距离为 dis[i]。因为边权为 0 的边存在,所以有 dis[i] >= dis[i+1]。其中还有 dis[0] = 0。

对于 i->j (i < j) 的边,有 dis[i] - 1 >= dis[j];对于 i->j (i > j) 的边,有 dis[i] + 1 >= dis[j]。

由于 dis 应该是满足三角形不等式的最大值,在没有负环的情况下有 dis[i] - 1 <= dis[i+1]。

注意到上面的不等式都是在 dis[i] 与 dis[i+1] 之间建立的,我们可以考虑差分:令 p[i] = dis[i] - dis[i + 1](注意不是 dis[i+1] - dis[i]),则有 0 <= p[i] <= 1。

对于 i->j (i < j) 的边,应该满足 \(\sum_{k=i}^{j-1}p[k] \ge 1\);对于 i->j (i > j) 的边,应该满足 \(\sum_{k=j}^{i-1}p[k] \le 1\)。这个可以根据上面的三角形不等式推导得到。

即:一个需要区间内至少包含 1 个 1,一个需要区间内最多包含 1 个 1。

然后我们就可以对这个 p 进行 dp 了。设 dp[i][j][k] 表示处理完前 i 位,往前数第 1 个 1 在 j 位置,第 2 个 1 在 k 位置。

转移时枚举第 i + 1 位填 0 还是填 1 即可。第一维显然可以滚动掉。

时间复杂度 O(n^3)。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 500;
const ll INF = ll(1E18);
int A[MAXN + 5][MAXN + 5], B[MAXN + 5][MAXN + 5], n;
// A[i][j] -> (p[i] + p[i+1] + ... p[j] >= 1) (i <= j)
// B[i][j] -> (p[i] + p[i+1] + ... p[j] <= 1) (i <= j)
ll SA[MAXN + 5][MAXN + 5], SB[MAXN + 5][MAXN + 5];
// SA[i][j] -> A[1][j] + A[2][j] + ... + A[i][j]
// SB[i][j] -> B[1][j] + B[2][j] + ... + B[i][j]
ll dp[2][MAXN + 5][MAXN + 5], f[2][MAXN + 5], g[2];
int main() {
scanf("%d", &n);
for(int i=1;i<=n;i++) {
for(int j=1;j<=i-1;j++) scanf("%d", &B[j][i-1]); // i -> j (i > j)
for(int j=i+1;j<=n;j++) scanf("%d", &A[i][j-1]);
}
for(int j=1;j<=n;j++)
for(int i=1;i<=n;i++)
SA[i][j] = A[i][j] + SA[i-1][j], SB[i][j] = B[i][j] + SB[i-1][j];
n--;
for(int j=1;j<=n;j++) {
for(int k=j+1;k<=n;k++)
dp[0][j][k] = INF;
f[0][j] = INF;
}
g[0] = 0;
for(int i=1;i<=n;i++) {
for(int j=1;j<i;j++) {
for(int k=j+1;k<i;k++)
dp[1][j][k] = dp[0][j][k], dp[0][j][k] = INF;
f[1][j] = f[0][j], f[0][j] = INF;
}
g[1] = g[0], g[0] = INF;
for(int j=1;j<i;j++) {
for(int k=j+1;k<i;k++) {
dp[0][j][k] = min(dp[0][j][k], dp[1][j][k] + SA[i][i] - SA[k][i] + SB[j][i]);
dp[0][k][i] = min(dp[0][k][i], dp[1][j][k] + SB[k][i]);
}
f[0][j] = min(f[0][j], f[1][j] + SA[i][i] - SA[j][i]);
dp[0][j][i] = min(dp[0][j][i], f[1][j] + SB[j][i]);
}
g[0] = min(g[0], g[1] + SA[i][i]);
f[0][i] = min(f[0][i], g[1]);
}
ll mn = INF;
for(int j=1;j<=n;j++) {
for(int k=j+1;k<=n;k++)
mn = min(mn, dp[0][j][k]);
mn = min(mn, f[0][j]);
}
mn = min(mn, g[0]);
printf("%lld\n", mn);
}

@details@

为了方便转移,多设了几个只含 1 个 1 / 不含任何 1 的状态。

我下一次要是再不开 long long 我就。。。

@atcoder - AGC036D@ Negative Cycle的更多相关文章

  1. AtCoder AGC036D Negative Cycle (图论、DP)

    题目链接 https://atcoder.jp/contests/agc036/tasks/agc036_d 题解 这都是怎么想出来的啊..目瞪口呆系列.. 第一步转化至关重要: 一张图中不存在负环意 ...

  2. Atcoder Grand Contest 036 D - Negative Cycle

    Atcoder Grand Contest 036 D - Negative Cycle 解题思路 在某些情况下,给一张图加或删一些边要使图合法的题目要考虑到最短路的差分约束系统.这一题看似和最短路没 ...

  3. AtCoder Grand Contest 036D - Negative Cycle

    神仙题?反正我是完全想不到哇QAQ 这场AGC真的很难咧\(\times 10086\) \(\bf Description\) 一张 \(n\) 个点的图,\(i\) 到 \(i+1\) 有连边. ...

  4. Solution -「AGC 036D」「AT 5147」Negative Cycle

    \(\mathcal{Descriprtion}\)   Link.   在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...

  5. 多校联训 DP 专题

    [UR #20]跳蚤电话 将加边变为加点,方案数为 \((n-1)!\) 除以一个数,\(dp\) 每种方案要除的数之和即可. 点击查看代码 #include<bits/stdc++.h> ...

  6. AOJ GRL_1_B: Shortest Path - Single Source Shortest Path (Negative Edges) (Bellman-Frod算法求负圈和单源最短路径)

    题目链接: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_B   Single Source Shortest Path ...

  7. AtCoder Grand Contest 036 A-C

    目录 \(\bf A - Triangle\) \(\bf B - Do\ Not\ Duplicate\) \(\bf C - GP 2\) \(\bf D - Negative \ Cycle\) ...

  8. AtCoder Grand Contest 036

    Preface 这篇已经鸽了好久的说,AGC037都打完了才回来补所以题目可能都记不大清楚了,如有错误请指正 这场感觉难度远高于上一场,从D开始就不会了,E没写(看了题解都不会写),F就是抄曲明姐姐的 ...

  9. AtCoder Grand Contest 036 简要题解

    从这里开始 比赛目录 Problem A Triangle 考虑把三角形移到和坐标轴相交,即 然后能够用坐标比较简单地计算面积,简单构造一下就行了. Code #include <bits/st ...

随机推荐

  1. java swing调试时线程显示名字

    一般有一个默认名字 但是具体运行到哪一个线程,需要猜 为了节约时间,提高效率 可以给线程写个中文名(因为默认就是英文,写中文,一眼就能挑出来) 以RTC定时器为例子 final TimerRtc ti ...

  2. vmware 与Device/Credential Guard不兼容

    解决办法 关闭hv 重启就完了

  3. day18 15.自定义连接池

    我们写的是连接池吗?Connection对象绝对不能关.现在写的玩意不是连接池.因为现在讲的是JDBC,连接池也是JDBC里面的,人家那是SUN公司定义的标准.标准,你那不是标准.既然是标准,你做连接 ...

  4. selenium(6):通过多种定位方式还是不能成功定位的原因

    场景:在成功修改密码后,会弹出一个修改成功的提示.通过id.xpath.class.css方式定位后,执行到这一步时候,就会出现错误. 原因:仔细检查了下代码,发现在提交修改的操作到修改成功的提示之间 ...

  5. JavaScript之HTML DOM Document 对象

    文档对象代表您的网页. 如果您希望访问 HTML 页面中的任何元素,那么您总是从访问 document 对象开始. 下面是一些如何使用 document 对象来访问和操作 HTML 的实例. 查找 H ...

  6. 《2019上半年DDoS攻击态势报告》发布:应用层攻击形势依然严峻,海量移动设备成新一代肉鸡

    2019年上半年,阿里云安全团队平均每天帮助用户防御2500余次DDoS攻击,与2018年持平.目前阿里云承载着中国40%网站流量,为全球上百万客户提供基础安全防御.可以说,阿里云上的DDoS攻防态势 ...

  7. 一文纵览EMAS 到底内含多少阿里核心技术能力

    申请阿里云EMAS,体验一站式移动研发平台,更多精彩尽在开发者会场 EMAS的整体定位是阿里巴巴移动技术对外输出的主窗口,沉淀了阿里巴巴近10年在移动互联网技术架构上的积累以及在一系列垂直场景中所实践 ...

  8. node.js(二)各种模块

    我们知道Node.js适合于IO密集型应用,不适合于CPU密集型应用.    JS和Node.js区别:         JS运行于客户端浏览器中,存在兼容性问题:数据类型:值类型+引用类型(ES+D ...

  9. 【Leetcode】两数之和,三数之和,四数之和

    两数之和 题目 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这 ...

  10. mysqldump命令之数据库迁移

    格式说明如下: mysqldump -h源主机IP -u源主机用户 -p源主机用户密码 数据库名 | mysql -h目标主机IP -u目标主机用户 -p目标用户密码 数据库名