• 差分约束


    差分约束

    (1) 求不等式组的可行解

    步骤:

    ​ [1] 先将每个不等式 xi < = xj + ck 转换成一条从xj 走到 xi ,长度为ck的一条边 即表示为 离源点距离dist[i]<=dist[j]+ck

    ​ [2] 找一个超级源点,使得该源点一定可以遍历到所有边。

    ​ [3]从源点求一遍单源最短路

    ​ 结果1:如果存在负环,则不等式组一定无解

    ​ 结果2:如果没有负环,则dist[i]就是不等式组的一个可行解

    (2) 如何求得最大值或最小值,最值是每个变量的最值。

    结论:

    ①如果求的是最小值,则应该求最长路(在所有下界里,求最大值)//下界就是去为了求最小,最大值就是求能满足条件的下界中的最大值,所求即最小值。

    ​ 注意:如果存在正环,则无解。

    ②如果求的是最大值,则应该求最短路。(上界的最小值)。

    ​ 注意:如果存在负环,则无解。

    如果求最小值,则应该是最长路,然后把所有的符号都变为>或>=

    如果求最大值,则应该是最短路,然后把所有的符号都变为<或<=

    例题

    cWing 1169. 糖果

    链接1169. 糖果 - AcWing题库

    AC代码:

    注意:边要加上超级源点的边,所以至少开2*m + n个边,否则会wa

    #include <iostream> 
    #include <cstring>
    #include <stack>
    using namespace std;
    /*
    1 a==b  a>=b+0  b>=a+0
    2 a<b   b>=a+1
    3 a>=b  a>=b
    4 a>b   a>=b
    5 a<=b  b>=a
    并且建立一个超级源点
     x=0
     i>=x+1
     
     建边时: i > = j + s 则 add(j,i,s)   
     后面的指向前边的,长度为s 
    */
    const int N = 1e5+5,M = 5e5+10;
    typedef long long ll;
    ll h[N],e[M],ne[M],idx;
    ll w[M];
    void add(ll a,ll b,ll c){
    	e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
    }
    ll dist[N];
    bool vis[N];
    ll cnt[N];
    stack<ll> q;
    ll n,k;
    
    bool spfa(){//在这里求最长路,并且要判断有无正环 
    	memset(dist,-0x3f,sizeof dist);
    	dist[0]=0;
    	q.push(0);
    	vis[0]=true; 
    	while(q.size()){
    		ll t=q.top();
    		q.pop();
    		vis[t]=false;
    		for(ll i=h[t];i!=-1;i=ne[i]){
    			ll j=e[i];
    			if(dist[j]<w[i]+dist[t]){
    				dist[j]=w[i]+dist[t];
    				cnt[j]=cnt[t]+1;
    				if(cnt[j]>=n+1) return false; 
    				if(!vis[j]){
    					q.push(j);
    					vis[j]=true;
    				}
    			}
    		}
    	}
    	return true;
    }
    
    int main(){
    	scanf("%lld%lld",&n,&k);
    	memset(h,-1,sizeof h); 
    	ll x,a,b;
    	for(ll i=0;i<k;i++){
    		scanf("%lld%lld%lld",&x,&a,&b);
    		if(x==1) add(b,a,0),add(a,b,0);
    		else if(x==2) add(a,b,1);
    		else if(x==3) add(b,a,0);
    		else if(x==4) add(b,a,1); 
    		else add(a,b,0); 
    	} 
    	for(ll i=1;i<=n;i++) add(0,i,1);
    	if(!spfa()){
    		printf("-1
    ");
    	}else{
    		long long ans=0;
    		for(ll i=1;i<=n;i++) {
    			ans+=dist[i];	
    		}
    		printf("%lld
    ",ans);
    	}
    }
    
    
  • 相关阅读:
    BNU 51002 BQG's Complexity Analysis
    BNU OJ 51003 BQG's Confusing Sequence
    BNU OJ 51000 BQG's Random String
    BNU OJ 50999 BQG's Approaching Deadline
    BNU OJ 50998 BQG's Messy Code
    BNU OJ 50997 BQG's Programming Contest
    CodeForces 609D Gadgets for dollars and pounds
    CodeForces 609C Load Balancing
    CodeForces 609B The Best Gift
    CodeForces 609A USB Flash Drives
  • 原文地址:https://www.cnblogs.com/AC673523745/p/14829713.html
Copyright © 2020-2023  润新知