zoukankan      html  css  js  c++  java
  • Atcoder Grand Contest 036 D

    Atcoder Grand Contest 036 D - Negative Cycle

    解题思路

    在某些情况下,给一张图加或删一些边要使图合法的题目要考虑到最短路的差分约束系统。这一题看似和最短路没什么关系,但有一个不那么经典的推论,对于一个点 (u) 不在负环上的一个充要条件是

    [forall_{ ext{Edge }v ightarrow u} dis(S,v)+weight(v, u)geq dis(S,u) ]

    其中 (S) 是图中任意与 (u) 联通的一点。

    随便新建一个源点 (S),我们令 (p_i=dis(S,i)) ,仅考虑原图的链可以得到 (p_i geq p_{i+1}) 。对于任意两点 (x,y (x<y)) ,新加的边 ((x, y), (y, x))分别满足 (p_x-1geq p_y,p_y+1geq p_x) 。这里看似推不下去了然而巧妙差分后能获得非常显然的结论,令 (q_i=p_i-p_{i+1}) ,移项可得

    [sum_{i=x}^{y-1} q_i geq 1,sum_{i=x}^{y-1}q_i leq 1 ]

    然后我们可以证明出,(q_i in {0,1}),这里比较容易,如果 (q_i <0) 原链的差分约束条件就不满足,如果 (q_i > 0) 则点 (i+1) 存在额外的 (-1) 入边 ((v,i+1),v< i),此时 (v)(i) 最坏情况可以走一段 (0) 链更新,所以 (q_i) 最多只能为 (1)

    然后我们就可以考虑 (q_i) 的每一位取 (0) 还是取 (1) ,然后删掉不合法的边,这个过程是可以 ( ext{DP}) 解决的,对于不满足 (sum q_i leq 1) 的情况,在其跨过第二个 (1) 的时候统计掉,对于 (sum q_i geq 1) 的情况,对于每一段连续的 (0) 统计即可,那么就可以令 (dp[i][j]) 为当前考虑到前 (i) 位且 (i)(1),上一个 (1)(j) 的答案,转移使用前缀和优化即可。

    code

    /*program by mangoyang*/ 
    #include<bits/stdc++.h>
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
        int ch = 0, f = 0; x = 0;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
        for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        if(f) x = -x;
    }
    const int N = 505;
    #define int ll
    int A[N][N], B[N][N], C[N][N], D[N][N], dp[N][N], n;
    signed main(){
    	read(n);
    	for(int i = 1; i <= n; i++){
    		for(int j = 1; j < i; j++) read(A[j][i]);
    		for(int j = i + 1; j <= n; j++) read(B[i][j]);
    	}
    	for(int i = 0; i <= n + 1; i++)
    		for(int j = i; j <= n + 1; j++){
    			if(i) C[i][j] += C[i-1][j];
    			for(int k = j; k <= n + 1; k++) C[i][j] += A[i][k];
    		}
    	for(int i = n + 1; i >= 0; i--)
    		for(int j = i; j <= n + 1; j++){
    			D[i][j] += D[i+1][j];
    			for(int k = i; k <= j; k++) D[i][j] += B[i][k];
    		}
    	memset(dp, 0x3f, sizeof(dp));
    	dp[0][0] = 0;
    	for(int i = 1; i <= n + 1; i++)
    		for(int j = 0; j < i; j++){
    			for(int k = 0; k <= j; k++) 
    				dp[i][j] = min(dp[i][j], dp[j][k] + C[j][i+1] - C[k][i+1] + D[j+1][i]);
    		}
    	int ans = inf;
    	for(int i = 0; i <= n; i++)
    		ans = min(ans, dp[n+1][i]);
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    centos7上修改lv逻辑卷的大小
    centos6上调整lv逻辑卷
    nginx的日志配置
    修改Linux系统默认编辑器
    mysqldump命令的安装
    centos7上设置中文字符集
    nginx的80端口跳转到443
    ubuntu上安装docker和docker-compose
    javascript递归、循环、迭代、遍历和枚举概念
    Lattice 开发工具Diamond 相关版本下载地址
  • 原文地址:https://www.cnblogs.com/mangoyang/p/11240437.html
Copyright © 2011-2022 走看看