• [模板][最短路] 差分约束系统


    差分约束系统

    定义 来自某度百科

    如果一个系统由 (n) 个变量和 (m) 个约束条件组成,形成 (m) 个形如 (a_i-a_j≤k) 的不等式 ((i,jin[1,n]), (k)为常数),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。

    简单来说,给你一组不等式:

    [left { egin{array}{} x_1 - x_2 le c_1 \ x_2 - x_3 le c_2 \ cdots \ x_i - x_j le c_k end{array} ight. ]

    求这组不等式的可行解。

    解法

    该问题等价于在一个有向图上求最短/长路,

    首先建立一个超级源点, 向每个节点链接一条边权为 (0) 的边,

    然后开始转化:

    1. 转化为最

      []

      x_1 le c_1 + x_2
      x_2 le c_2 + x_3
      cdots
      x_i le c_k + x_j
      end{array} ight.

      []

    2. 转化为最

      []

      x_1 ge -c_1 + x_2
      x_2 ge -c_2 + x_3
      cdots
      x_i ge -c_k + x_j
      end{array} ight.

      []

    我们要做的就是从大于号左边(小于号右边)向大于号右边(小于号左边)连接一条边权为 (c_i)((-c_i)) 的边,跑最短路即可。

    无解?

    联系最短路,发现当图上有负环无解,

    所以跑 (SPFA) 即可。

    模板

    Luogu P5960 [模板] 差分约束算法

    // 注释掉的是跑最长路找最小正数可行解的方法
    # include <iostream>
    # include <cstdio>
    # include <queue>
    # include <cstring>
    # define MAXN 5005
    # define MAXM 10005
    
    using namespace std;
    
    struct edge{
    	int u, v, next, w;
    }e[MAXM];
    int hd[MAXM], cntE;
    
    void AddE(int u, int v, int w){
    	e[++cntE].u = u, e[cntE].v = v, e[cntE].next = hd[u], hd[u] = cntE;
    	e[cntE].w = w;
    }
    
    //
    int dis[MAXN], cntQ[MAXN];
    bool inQ[MAXN];
    
    bool SPFA(int from, int lim){
    	queue<int>Q;
    	memset(inQ, 0, sizeof(inQ));
    	memset(dis, 0x3f, sizeof(dis));
        // for(int i = 1; i <= lim-1; i++){
        //     dis[i] = -100000;
        // }
    	
    	dis[from] = 0;
    	Q.push(from); inQ[from] = 1;
    
    	while(!Q.empty()){
    		int now = Q.front(); Q.pop();
    		inQ[now] = 0;
    
    		for(int i = hd[now]; i; i = e[i].next){
                if(dis[e[i].v] > dis[now] + e[i].w){
    			// if(dis[e[i].v] < dis[now] + e[i].w){
    				dis[e[i].v] = dis[now] + e[i].w;
    
    				if(!inQ[e[i].v]){
    					Q.push(e[i].v); inQ[e[i].v] = 1;
    					cntQ[e[i].v] += 1;
    
    					if(cntQ[e[i].v] == lim){
    						return false;
    					}
    				}
    			}
    		}
    	}
    
    	return true;
    }
    
    //
    int main(){
    	int n, m;
    	cin>>n>>m;
    
    	for(int i = 1, u, v, w; i <= m; i++){
    		cin>>u>>v>>w;
    		AddE(v, u, w); // 注意这里的连边方向,应该是从大于连向小于
            // AddE(u, v, -w);
    	}
    	
    	for(int i = 1; i <= n; i++){
    		AddE(0, i, 0);
    	} // 建立超级源点
    
    	bool chk = SPFA(0, n+1);
    	
    	if(chk){
    		for(int i = 1; i <= n; i++){
    			cout<<dis[i]<<' ';
    		}
    	}
    	else{
    		cout<<"NO";
    	}
    
    	return 0;
    }
    
    
  • 相关阅读:
    WebApi接口访问频率控制的实现
    一分钟告诉你究竟DevOps是什么鬼?
    大多数企业不知道的隐形成本
    29个网络营销必须知道的数据
    如何让自己的生活有品质感?
    一则有意思的产品小故事
    免费学习编程的9个地方
    营销,就是营销人性的弱点!
    网络营销行业十大看了就想吐的“滥词”
    高质量的内容是SEO的关键
  • 原文地址:https://www.cnblogs.com/Foggy-Forest/p/13404428.html
Copyright © 2020-2023  润新知