• 浅谈差分约束


    浅谈差分约束

    1.定义:

    ​ 如果一个系统由(n)个变量和(m)个约束条件组成,并且条件都为形如(a_i-a_jle k)的不等式,则称其为差分约束系统。

    ​ 差分约束系统是一种特殊的(n)元一次不等式组,每个约束条件都为两个变量作差构成。


    2.模型转换:

    ​ 求解差分约束系统,可以转化成图论中的单源最短路问题。

    ​ 对于一个不等式:(a_i-a_jle k),经过变换,可以得到(a_ile a_j+k)的形式,这与最短路中的三角不等式十分相似,即:(dist_yle dist_x + v)

    ​ 所以我们可以把模型转化为:连接(m)条由(a_j)指向(a_i)、边权为(k)的单向边。再增加一个与所有点连通的超级源点,使其相连的边权都为0。再以超级源点为起点,求一遍单源最短路,节点(i)(dist)值即为该不等式的解。

    ​ 若形成的图存在负权环,则说明该不等式系统没有解。


    3.例题与代码实现:

    洛谷:P1993

    洛谷传送门

    题解:

    ​ 差分约束模板题。

    ​ 依据题意建图,再用SPFA判断负环即可。

    ​ 对于第一种信息:(a-bge c),可转化成 (ble a-c) 的形式,即连一条从(a)指向(b)、边权为(-c)的边

    ​ 对于第二种信息:(a-ble c),可转化成(a le b+c) 的形式,即连一条从(b)指向(a)、边权为(c)的边

    ​ 对于第三种信息:(a=b),需连一条联通(a、b)、边权为(0)的双向边

    代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    #define maxn 50100
    int head[maxn],nxt[maxn],to[maxn],val[maxn],tot=0;
    void add(int x,int y,int z)
    {
    	to[++tot]=y;
    	nxt[tot]=head[x];
    	val[tot]=z;
    	head[x]=tot;
    }
    int dis[maxn],inq[maxn],cnt[maxn];
    bool spfa(int s)
    {
    	queue<int> q;
    	q.push(s);
    	memset(inq,0,sizeof(inq));
    	memset(cnt,0,sizeof(cnt));
    	inq[s]=1;
    	memset(dis,0x3f,sizeof(dis));
    	dis[s]=0;
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		inq[x]=0;
    		for(int i=head[x];i;i=nxt[i])
    		{
    			int y=to[i];
    			if(dis[y]>dis[x]+val[i])
    			{
    				dis[y]=dis[x]+val[i];
    				cnt[y]=cnt[x]+1;
    				if(cnt[y]>=n)
    				return 0;
    				if(!inq[y])
    				{
    					q.push(y);
    					inq[y]=1;
    				}
    			}
    		}
    	}
    	return 1;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		int opt;
    		scanf("%d",&opt);
    		if(opt==1)
    		{
    			int x,y,z;
    			scanf("%d%d%d",&x,&y,&z);
    			add(x,y,-z);
    		}
    		if(opt==2)
    		{
    			int x,y,z;
    			scanf("%d%d%d",&x,&y,&z);
    			add(y,x,z);
    		}
    		if(opt==3)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			add(x,y,0);
    			add(y,x,0);
    		}
    	}
    	for(int i=1;i<=n;i++)
    	add(0,i,0);
    	if(spfa(0))
    	printf("Yes
    ");
    	else 
    	printf("No
    ");
    }
    
  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/Marcelo/p/14026113.html
Copyright © 2020-2023  润新知