洛谷P3275 [SCOI2011]糖果

差分约束系统

  • 对于多组形如\(B-A \geq C\) 的不等式组求出一组解,其中,\(A\)\(B\) 为变量,\(C\) 为常数

转化为$$A+C\leq B$$,注意到该形式形似于SPFA松弛过程中的三角形不等式 $$dis[u]+w(u,v)\leq dis[v]$$

于是,连一条\(A\)\(B\)的长度为\(C\)的有向边。因为建出的图可能不连通,最后规定一个源点s(通常为0号点或n+1号点)对每个点连一条长度为k的边,进行SPFA,存在正环则无解,否则dis数组的值对应每个变量取值,满足所有变量取值都大于等于最初从源点连的边权k。

  • 本题的五种情况(所有变量取值均为正整数):
  1. \(A=B\) 转化为 \(A+0\leq B\)\(B+0\leq A\)
  2. \(A<B\) 转化为\(A+1\leq B\)
  3. \(A>B\) 转化为 \(B+1\leq A\)
  4. \(A\leq B\) 转化为 \(A+0 \leq B\)
  5. \(A\geq B\) 转化为 \(B+0\leq A\)
  • 需要 SPFA dfs版 以及 反向连边 否则会TLE (面向数据编程
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100005,maxm=100005,inf=0x3f3f3f3f;
int n,m,tot,dis[maxn],cnt[maxn];
long long ans;
bool v[maxn];
struct edge{
    #define New(p) p=&e[++tot]
    int to,dis;edge *Nex;
}e[maxm*3],*head[maxn];
inline void add(int x,int y,int z){
    edge *p;New(p);p->dis=z;p->to=y;p->Nex=head[x];head[x]=p;
}
bool SPFA(int u=0){
    v[u]=true;
    for(edge *i=head[u];i!=NULL;i=i->Nex){
        if(dis[u]+i->dis>dis[i->to]){
            dis[i->to]=dis[u]+i->dis;
            if(v[i->to]) return false;
            if(!SPFA(i->to)) return false;
        }
    }
    v[u]=false;
    return true;
}
int main(){
    scanf("%d%d",&n,&m);
    for(register int i=1,flag,x,y;i<=m;++i){
        scanf("%d%d%d",&flag,&x,&y);
        if(flag==1) add(x,y,0),add(y,x,0);
        else if(flag==2) add(x,y,1);
        else if(flag==3) add(y,x,0);
        else if(flag==4) add(y,x,1);
        else if(flag==5) add(x,y,0);
    }
    for(register int i=n;i>=1;--i) {//玄学连边
        add(0,i,1);
        dis[i]=-inf;
    }
    if(!SPFA()) puts("-1");
    else {
        for(int i=1;i<=n;++i) ans+=dis[i];
        printf("%lld",ans);
    }
    return 0;
}
posted @ 2019-03-17 00:19  宇興  阅读(168)  评论(0编辑  收藏  举报