• 浅谈差分约束系统


    什么是差分约束系统?

    百度百科

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

    具体怎么实现?

    前置技能(简而言之就是单源最短路径)

    ①链式前向星建图或者vector建图(这个好像用邻接矩阵也可以)

    ②SPFA

    如何建图?

    ①先看题目要求求什么,求最大值那么就是跑最短路,求最小值那么就是跑最长路

    怎么跑最长路?

    只需要将SPFA中的符号反向即可,并且把inf设置成-inf

    ②看清楚求的是什么了之后还得看符号。首先所有转换的符号必须是带等于号的,也就是说必须是≥≤才可以,><那么就不行(这个还需要特殊转换,稍后再讲)

    ③如果求最大值,也就是最短路那么符号必须统一成≤,如果有a-b<c那么变成 a-b<=c-1。如果有≥,那么就两边乘以负号例如 b-a>=c->a-b<=-c

    ④如果求最小值,也就是最长路转换格式同④

    ⑤如果要判断解是不是存在那就是SPFA判断是否存在负环,具体做法是在要入队的那一步加一个辅助数组计数,如果一个点入队次数超过总的点的个数,那么就不存在解了。

    if(!bk[G[p][i].to])
            {
              bk[G[p][i].to]=1;
              if(++vis[G[p][i].to]>n)
              return cout<<-1,0;
              q.push(G[p][i].to);
            }
    

    ⑥最终按照第二个数为源点第一个数为去的点,第三个数为权值建图即可即

    a-b>=c
    等价于
    G[b].push_back((node){a,c});
    

    如何找答案?

    直接输出dis数组即可

    完整代码(Layout POJ - 3169 )

    #include <iostream>
    #include <vector>
    #include <queue>
    #include <climits>
    using namespace std;
    struct node
    {
      int to,cost;
    };
    vector<node> G[10000];
    long long dis[10000],bk[10000],vis[10000];
    const int inf=INT_MAX;
    int main()
    {
      ios::sync_with_stdio(0);
      cin.tie(0);
      cout.tie(0);
      int n,t1,t2;
      cin>>n>>t1>>t2;
      while(t1--)
      {
        int k1,k2,k3;
        cin>>k1>>k2>>k3;
        G[k1].push_back((node){k2,k3});
      }
      while(t2--)
      {
        int k1,k2,k3;
        cin>>k1>>k2>>k3;
        G[k2].push_back((node){k1,-k3});
      }
      for(int i=1;i<=n;i++)
      dis[i]=i==1?0:inf;
      queue<int> q;
      q.push(1);
      while(q.size())
      {
        int p=q.front();
        q.pop();
        bk[p]=0;
        for(int i=0;i<G[p].size();i++)
        {
          if(dis[G[p][i].to]>dis[p]+G[p][i].cost)
          {
            dis[G[p][i].to]=dis[p]+G[p][i].cost;
            if(!bk[G[p][i].to])
            {
              bk[G[p][i].to]=1;
              if(++vis[G[p][i].to]>n)
              return cout<<-1,0;
              q.push(G[p][i].to);
            }
          }
        }
      }
      if(dis[n]<INT_MAX)
      cout<<dis[n];
      else
      cout<<-2;
    }
    
  • 相关阅读:
    IP掩码的作用
    linux shell 笔记
    ubuntu apt-get Failed to fetch Temporary failure resolving 'security.ubuntu.com'
    ubuntu 16.04 & 18.04 远程桌面使用
    取消Ubuntu开机硬盘自检
    linux shell 脚本输入参数解析
    Ubuntu 16.04 + python3 源码 安装+使用labelImg最新版
    用tinyxml2读写xml文件_C++实现
    常用工具问题及解决方案
    可视化调试工具
  • 原文地址:https://www.cnblogs.com/baccano-acmer/p/10032865.html
Copyright © 2020-2023  润新知