差分约束系统【模板】

差分约束系统:如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如 xj - xi<= bk ( i , j ∈ [1,n],k ∈ [1,m]),则称其为差分约束系统。

例如如下的约束条件:

X1 - X2 <= 0 X1 - X5 <= -1

X2 - X5 <= 1 X3 - X1 <= 5

X4 - X1 <= 4 X4 - X3 <= -1

X5 - X3 <= -3 X5 - X4 <= -3

全都是两个未知数的差小于等于某个常数(大于等于也可以,因为左右乘以-1就可以化成小于等于)。这样的不等式组就称作差分约束系统。

差分约束系统求解过程:

1.新建一个图,N个变量看作N个顶点,M个约束条件作为M条边。每个顶点Vi分别对于一个未知量,每个有向边对应两个未知量的不等式。

2.为了保证图的连通性,在图中新加一个节点Vs,图中每个节点Vi都能从Vs可达,建立边w(Vs,Vi) = 0。

3.对于每个差分约束Xj - Xi <= Bk(这里是小于等于号),则建立边w(Xi,Xj) = Bk。

4.初始化Dist[] = INF,Dist[Vs] = 0.

5.求解以Vs为源点的单源最短路径,推荐用SPFA,因为一般可能存在负值。

如果图中存在负权回路,则该差分约束系统不存在可行解。

Vs到某点如果不存在最短路径,即最短路为INF,则对于该点表示的变量可以取任意值,都能满足差分约束的要求,如果存在最短路径,则得到该变量的最大值。

上述过程最终得到的解为满足差分约束系统各项的最大值。

注意点:

1. 如果要求最大值想办法把每个不等式变为标准 x - y <= k 的形式,然后建立一条从 y 到 x 权值为 k 的边,变得时候注意 x - y < k => x - y <= k-1。

2. 如果要求最小值的话,变为 x - y >= k 的标准形式,然后建立一条从 y到 x 权值为 k 的边,求出最长路径即可。

3. 如果权值为正,用Dijkstra,SPFA,BellmanFord都可以,如果为负不能用Dijkstra,并且需要判断是否有负环,有的话就不存在。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x7fffffff
using namespace std;
const int MAXN = 1100;
const int MAXM = 30030;

struct EdgeNode
{
    int to;
    int w;
    int next;
}Edges[MAXM];

int Head[MAXN],Dist[MAXN],vis[MAXN],outque[MAXN],id;

void AddEdges(int u,int v,int w)
{
    Edges[id].to = v;
    Edges[id].w = w;
    Edges[id].next = Head[u];
    Head[u] = id++;
}
void SPFA(int s,int N)
{
    int ans = 0;
    memset(vis,0,sizeof(vis));
    memset(outque,0,sizeof(outque));
    for(int i = 1; i <= N; ++i)
        Dist[i] = INF;
    Dist[s] = 0;
    vis[s] = 1;
    queue<int> Q;
    Q.push(s);
    while( !Q.empty() )
    {
        int u = Q.front();
        Q.pop();
        vis[u] = 0;
        outque[u]++;
        if(outque[u] > N+1) //如果出队次数大于N,则说明出现负环
        {
            ans = -1;
            break;
        }
        for(int i = Head[u]; i != -1; i = Edges[i].next)
        {
            int temp = Dist[u] + Edges[i].w;
            if(temp < Dist[Edges[i].to])
            {
                Dist[Edges[i].to] = temp;
                if( !vis[Edges[i].to])
                {
                    vis[Edges[i].to] = 1;
                    Q.push(Edges[i].to);
                }
            }
        }
    }

    if(ans == -1)   //出现负权回路,不存在可行解
        printf("-1\n");
    else if(Dist[N] == INF) //可取任意值,都满足差分约束系统
        printf("-2\n");
    else
        printf("%d\n",Dist[N]);  //求使得源点 s 到 终点 t 的最大的值
}

int main()
{
    int N,ML,MD,u,v,w;
    while(~scanf("%d%d%d", &N, &ML, &MD))
    {
        memset(Head,-1,sizeof(Head));
        id = 0;
        for(int i = 0; i < ML; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            AddEdges(u,v,w);//建边 u - v <= w
        }
        for(int i = 0; i < MD; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            AddEdges(v,u,-w);//建边 v - u <= w
        }
//这里不加也可以
//        for(int i = 1; i < N; ++i)
//            AddEdges(i+1,i,0);
        SPFA(1,N);  //求使得源点 s 到 终点 t 的最大的值
    }

    return 0;
}
时间: 2024-08-30 05:41:29

差分约束系统【模板】的相关文章

UVA 11478 bf+差分约束系统+二分逼近

Halum You are given a directed graph G(V, E) with a set of vertices and edges. Each edge (i, j) that connects some vertex i to vertex j has an integer cost associated with that edge. Define the operation Halum(v, d) to operate on a vertex v using an

差分约束系统

差分约束系统是指一系列不等式: $$ X_j - X_i \le C_{ij}(1\le i, j \le n) $$ 当然 i,j 不必取遍 1-n,而且在扩展的状况下,对于每个(i,j),可以由多个 $C_{ij}$,但是我们很容易把它们化成一个不等式. 在求解不等式组之前,我们可以分析一下这个不等式组的性质. 1. 这个不等式组是可以无解的,比如: $$X_1 - X_2 \le -1 \\ X_2 - X_3 \le -1 \\ X_3 - X_1 \le -1$$ 否则三个不等式相加得

UVa 515 - King (差分约束系统 + SPFA求带负权最短路)

下面是差分约束系统的详细介绍,以及解决方法~ 摘抄自 xuezhongfenfei(他好像也是转的....) 差分约束系统 X1 - X2 <= 0 X1 - X5 <= -1 X2 - X5 <= 1 X3 - X1 <= 5 X4 - X1 <= 4 X4 - X3 <= -1 X5 - X3 <= -3 X5 - X4 <= -3 不等式组(1) 全都是两个未知数的差小于等于某个常数(大于等于也可以,因为左右乘以-1就可以化成小于等于).这样的不等式组

差分约束系统 初见

今天初次学习差分约束系统,很神奇的东西 定义: 如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如xj-xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints).亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法. 求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题. 其实在一些问题中需求最小值或最大值,同时需要满足一系列的不等式关系,这样就可以用到差分约束系统了,对于求最小值的问

ZOJ 3668 Launching the Spacecraft (差分约束系统,最短路)

题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3668 题意: 给一个初始值为0的长度为n的区间,给m个约束l,r,a,b,表示从l到r的区间和>=a且<=b,且每个数的范围为-10000~10000,问这个区间的每个数是多少,要求数尽可能大,且序列字典序最大. 方法: 差分约束系统,以前缀和表示一个节点a[i] 建图:根据下面约束条件建图 a[i]-a[i-1]<=10000 a[i-1]-a[i]&l

POJ 2983 Is the Information Reliable?(差分约束系统)

题目地址:POJ 2983 这题刚上来完全不知道跟差分约束系统有什么关系.....后来发现只要判个负环就可以.. 因为假如有冲突的话会形成一个负环.之所以建图加上一个正值一个负值,是因为这样的话,像1 2 4和1 2 3这样的数据就会形成一个负环.这个方法还是很巧妙的...然后对于V的那些不清楚的位置,就会跟P的那些等式联立形成一个不等式,然后在用最短路判环的过程中就用松弛来解决. 代码如下: #include <iostream> #include <cstdio> #inclu

【POJ 1201】 Intervals(差分约束系统)

[POJ 1201] Intervals(差分约束系统) 11 1716的升级版 把原本固定的边权改为不固定. Intervals Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23817   Accepted: 9023 Description You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a p

差分约束系统--详讲

------------差分约束题目请戳:差分约束题集暨报告 总的开说差分约束问题就是给出一系列不等式然后求问某一式子的最大值或者最小值. 差分约束问题具体解释: 比方有这样一组不等式: X1 - X2 <= 0 X1 - X5 <= -1 X2 - X5 <= 1 X3 - X1 <= 5                   不等式组(1) X4 - X1 <= 4 X4 - X3 <= -1 X5 - X3 <= -3 X5 - X4 <= -3 全都是

浅谈差分约束系统——图论不等式的变形

浅谈差分约束系统——图论不等式的变形 ----yangyaojia 版权声明:本篇随笔版权归作者YJSheep(www.cnblogs.com/yangyaojia)所有,转载请保留原地址! 一.定义 如若一个系统由n个变量和m个不等式组成,并且这m个不等式对应的系数矩阵中每一行有且仅有一个1和-1,其它的都为0,这样的系统称为差分约束( difference constraints )系统. 二.分析 简单来说就是给你n个变量,给m个形如x[i]-x[j]≥k①或x[i]-x[j]≤k②.求两