• 差分约束系统


    差分约束系统只是对最短路算法的一种应用,没有什么新的算法,只是对于具体问题的建图方法的确定

    差分约束系统解决的问题是不等式组的求解:

    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的得到统一的不等号方向的不等式组。

    这个不等式组一定是无解和无数解两种情况,因为如果是存在任意一组解,{x1,x2,x3,x4,x5},我们都可以通过{x1+k,x2+k,x3+k,x4+k,x5+k}得到一个新的解。所以解的个数是无数的。

    因为每个数都加k,他们任意两个数之间的差是不变的,所以对于不等式没有影响。


    与最短路联系

    B - A <= c     (1)

    C - B <= a     (2)

    C - A <= b     (3)

     如果要求C-A的最大值,可以知道max(C-A)= min(b,a+c),而这正对应了下图中C到A的最短路。 

    差分约束建图技巧

    1.对于一个全部都是<=号的不等式组,我们可以将每个式子转化为Xi<=Xj+W(i,j),那么就建一条边,Xj->Xi=W(i,j),然后利用最短路径解决问题,在x0定死的情况下,求得最小值

    2.对于一个全部都是>=号的不等式组,我们可以将每个式子转化为Xi>=Xj+W(i,j),那么就建一条边,Xj->Xi=W(i,j),然后利用最长路径解决问题,在x0定死的情况下,求得最大值

    如果dis[Xi]为inf或-inf,那么Xi为任意解

    如果求最短路的过程中出现负环,那么说明该不等式组无解


    来看看一道例题

    【代码实现】

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include<queue>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn=1e5+5;
     7 const int INF=1e9+7;
     8 struct sd{
     9     int to,ww,next;
    10 }edge[maxn<<1];
    11 queue<int> que;
    12 int dis[maxn],num[maxn],head[maxn],n,m,cnt;
    13 bool vis[maxn];
    14 void add_edge(int a,int b,int ww)
    15 {
    16     edge[++cnt].next=head[a];
    17     edge[cnt].to=b;
    18     edge[cnt].ww=ww;
    19     head[a]=cnt;
    20 }
    21 bool spfa()
    22 {
    23     for(int i=1;i<=n;i++)
    24     dis[i]=1,vis[i]=1,que.push(i);
    25     while(!que.empty())
    26     {
    27         int v=que.front();que.pop();vis[v]=0;
    28         for(int i=head[v];i;i=edge[i].next)
    29         {
    30             int to=edge[i].to;
    31             if(dis[to]<dis[v]+edge[i].ww)
    32             {
    33                 dis[to]=dis[v]+edge[i].ww;
    34                 if(!vis[to]) 
    35                 {
    36                     if(++num[to]>n) return false;
    37                     vis[to]=1,que.push(to);
    38                 }
    39             }
    40         }
    41     }
    42     return true;
    43 }
    44 int main()
    45 {
    46     int ord,a,b;
    47     long long ans=0;
    48     scanf("%d%d",&n,&m);
    49     for(int i=1;i<=m;i++)
    50     {
    51         scanf("%d%d%d",&ord,&a,&b);
    52         if(ord==1) add_edge(a,b,0),add_edge(b,a,0);
    53         if(ord==2) {if(a==b){printf("-1");return 0;}add_edge(a,b,1);}
    54         if(ord==3) add_edge(b,a,0);
    55         if(ord==4) {if(a==b){printf("-1");return 0;}add_edge(b,a,1);}
    56         if(ord==5) add_edge(a,b,0);
    57     }
    58     if(!spfa()) {printf("-1");return 0;}
    59     for(int i=1;i<=n;i++) ans+=dis[i];
    60     printf("%lld",ans);
    61     return 0;
    62 }
  • 相关阅读:
    i春秋暑期训练营丨渗透测试工程师开课啦
    CTF必备技能丨Linux Pwn入门教程——环境配置
    i春秋四周年中奖名单出炉丨确认过眼神,你是中奖人
    i春秋四周年福利趴丨一纸证书教你赢在起跑线
    「你学习,我买单」i春秋四周年精品课程福利专场
    i春秋四周年庆典狂欢丨价值6000元的Web安全课程免费送啦
    倒计时3天!i春秋四周年盛典狂欢,钜惠不停
    「学习攻略」0基础转型白帽黑客第一步是什么?
    奖金高达150万元的NEST即将上线,速来报名
    「白帽挖洞技能」YxCMS 1.4.7 漏洞分析
  • 原文地址:https://www.cnblogs.com/genius777/p/9163103.html
Copyright © 2020-2023  润新知