[AGC036D] Negative Cycle
一、题目
二、解法
首先有一个根本想不到的题意转化:不存在负环等价于存在一组合法的差分约束的解。
设差分约束的合法解是 ,我们可以把所有边转化成不等式。图上初始的 条边,带来的限制是 ,可以进一步转化为差分:
对于边 ,满足 ,即 ,那么 ,也就是差分数组在 的区间和如果 ,那么边 就可以保留。换句话说如果区间和 那么需要删去。
对于边 ,满足 ,即 ,那么 ,也就是差分数组在 的区间和如果 ,那么边 就可以保留。换句话说如果区间和 那么需要删去。
不难发现如果 ,那么可以调整成 ,不难发现答案不变劣,所以最终的答案
那么我们可以规划每个位置上的 ,然后删去不合法的边。根据代价计算的特性,我们可以定义 表示考虑前 为个位置,其中 ,上一个等于 的位置是 ,需要删去边的最小权值。转移枚举 ,考虑如何计算代价。
考虑左右端点都在 中的第一类边是需要删去的。左端点在 ,右端点在 的第二类边是需要删去的,这可以需处理二维前缀和轻松计算,时间复杂度
#include <cstdio>
#include <iostream>
using namespace std;
const int M = 505;
#define int long long
const int inf = 1e18;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,ans,a[M][M],b[M][M],f[M][M];
void upd(int &x,int y) {x=min(x,y);}
int val(int k,int j,int i)
{
return b[j+1][i]+a[n][j]-a[i][j]-a[n][k]+a[i][k];
}
signed main()
{
n=read();ans=inf;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i^j) a[i][j]=read();
for(int l=n;l>=1;l--)
for(int r=l;r<=n;r++)
b[l][r]=b[l+1][r]+b[l][r-1]
-b[l+1][r-1]+a[l][r];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
for(int i=1;i<n;i++)
{
f[i][0]=val(0,0,i);
upd(ans,f[i][0]+val(0,i,n));
for(int j=1;j<i;j++)
{
f[i][j]=inf;
for(int k=0;k<j;k++)
upd(f[i][j],f[j][k]+val(k,j,i));
upd(ans,f[i][j]+val(j,i,n));
}
}
printf("%lld\n",ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2021-04-02 [多校联考2021] 模拟赛3