• [AGC036D] Negative Cycle


    一、题目

    点此看题

    二、解法

    首先有一个根本想不到的题意转化:不存在负环等价于存在一组合法的差分约束的解

    设差分约束的合法解是 \(x_1,x_2...x_n\),我们可以把所有边转化成不等式。图上初始的 \(n-1\) 条边,带来的限制是 \(x_i\geq x_{i+1}\),可以进一步转化为差分:\(q_i=x_{i}-x_{i+1}\geq 0\)

    对于边 \(i\rightarrow j(i<j)\),满足 \(x_i-1\geq x_j\),即 \(x_i-x_j\geq 1\),那么 \(q_i+q_{i+1}...q_{j-1}\geq 1\),也就是差分数组在 \([l,r)\) 的区间和如果 \(\geq 1\),那么边 \(l\rightarrow r\) 就可以保留。换句话说如果区间和 \(=0\) 那么需要删去。

    对于边 \(i\rightarrow j(i>j)\),满足 \(x_i+1\geq x_j\),即 \(x_j-x_i\leq 1\),那么 \(q_j+q_{j+1}...q_{i-1}\leq 1\),也就是差分数组在 \([l,r)\) 的区间和如果 \(\leq 1\),那么边 \(r\rightarrow l\) 就可以保留。换句话说如果区间和 \(\geq 2\) 那么需要删去。

    不难发现如果 \(q_i\geq 2\),那么可以调整成 \(q_i=1\),不难发现答案不变劣,所以最终的答案 \(q_i=\{0,1\}\)

    那么我们可以规划每个位置上的 \(q_i\),然后删去不合法的边。根据代价计算的特性,我们可以定义 \(f[i][j]\) 表示考虑前 \(i\) 为个位置,其中 \(q_i=1\),上一个等于 \(1\) 的位置是 \(j\),需要删去边的最小权值。转移枚举 \(k\),考虑如何计算代价。

    考虑左右端点都在 \((j,i]\) 中的第一类边是需要删去的。左端点在 \((k,j]\),右端点在 \((i,n]\) 的第二类边是需要删去的,这可以需处理二维前缀和轻松计算,时间复杂度 \(O(n^3)\)

    #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);
    }
    
  • 相关阅读:
    SpringCloud系列——TX-LCN分布式事务管理
    SpringCloud系列——限流、熔断、降级
    SpringBoot系列——Logback日志,输出到文件以及实时输出到web页面
    常用的js、java编码解码方法
    WebSocket数据加密——AES与RSA混合加密
    使用Fiddler重定向App的网络请求
    C# 调用 taskkill命令结束服务进程
    Install .Net Core For CentOS
    cron表达式详解[转]
    WinServer远程部署系统打包批处理文件
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/16091974.html
Copyright © 2020-2023  润新知