• 差分约束学习笔记


    2023.5.6 写的太烂了重新写

    差分约束系统

    定义

    差分约束系统是一种特殊的 n 元一次不等式组,它包含 n 个变量 x1,x2,...,xn 以及 m 个约束条件,每一个约束条件都是两个其中的变量做差构成的,形如 xixjck,其中 1i,jn,ij,1km 并且 ck 是常数(可以为正数或非正数)。
    ------- OI Wiki

    通俗一点讲,这类问题都是给定 n 个变量,m 个限制,类似于:

    {op1:x1x2=c1op2:x4xn=c2......opm:xnx3=cm

    有了这些条件,一般的题目会让你求出一组合法的解,也就是求这 n 个变量的合法的值。

    过程

    我们可以建一个超级源点,然后向每一个点连一条边权为 0 的边,然后跑单源最短路;而上面的 m 个限制都可以变形为 xixj+ck,这个东西很容易想到我们在跑最短路的时候的松弛操作里的 dis[v]dis[u]+w,因此我们就可以把每一个变量看作是一个图中的点,对于每一个条件 xixjck,从 ji 连一条边权为 ck 的有向边。

    我们在求解的时候一般用 SPFA 来跑,虽然他最坏的时间复杂度是 O(nm) 的,但是我们的差分约束里面要是有负环的话,就说明是无解,再加上有负边权,SPFA 这个已死的算法成了最好的方法,更何况他在一些随机的图中跑的飞快。

    最后一个问题,最后转化的式子是 xixj+ck,为什么跑最短路?

    但是我觉得,当你建图的时候使用的是 xixjck 形式的方程组建图时,即 ji 连一条权值为 ck 的边,应该选择跑最短路。

    如果使用的是 xisjck 形式的方程组来建图时,应该选择跑最长路。

    P5960 【模板】差分约束算法

    code:

    #include
    #define INF 0x3f3f3f3f
    #define N 50100
    using namespace std;
    int n,m,cnt,head[N];
    queue<int>q;
    struct SB{int w,v,next;}e[N<<1];
    int dis[N],tot[N],vis[N];
    inline void add(int u,int v,int w)
    {
    	e[++cnt].v=v;
    	e[cnt].w=w;
    	e[cnt].next=head[u];
    	head[u]=cnt;
    }
    int SPFA()
    {
    	
    	q.push(0);
    	vis[0]=1;
    	tot[0]++;
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=head[u];i;i=e[i].next)
    		{
    			int v=e[i].v,w=e[i].w;
    			if(dis[v]>dis[u]+w)
    			{
    				dis[v]=dis[u]+w;
    				q.push(v);
    				vis[v]=1;
    				tot[v]++;
    				if(tot[v]==n+1)
    				return 0;
    			}
    		}
    	}
    	return 1;
    }
    int main()
    {
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    	  dis[i]=INF;
    	for(int i=1;i<=n;i++)
    	  add(0,i,0);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,z;
    		cin>>x>>y>>z;
    		add(y,x,z);
    	}
    	if(!SPFA())
    	  cout<<"NO"<else
    	  for(int i=1;i<=n;i++)
    		cout<" ";
    	return 0;
    }
    
  • 相关阅读:
    HTML5七夕情人节表白网页制作【新年倒计时白色雪花飘落】HTML+CSS+JavaScript CSS特效
    秋日有感之秋诉-于光
    Github每日精选(第18期):聊天机器人ChatterBot
    汇编指令 栈现场保护 算数运算 位运算 比较指令 跳转指令 循环指令 寻址方式
    13 Igress,集群进出流量的总管
    JavaScript防抖和节流(从认识到理解到手写)
    西门子6ES72881ST600AA0
    【网络通讯开发系列】如何抓取终端设备的TLS报文(一)
    Netty的拆包粘包问题
    服务器挂机
  • 原文地址:https://www.cnblogs.com/Multitree/p/16756214.html