差分约束学习笔记

不等式可以想到差分约束

  1. 注意题目中隐含的不等式条件。
  2. 最小值:最长路 式子化成 \(d_x - d_y \ge k\) 的形式,连边 \((y,x,k)\)
    最大值:最短路 式子化成 \(d_x - d_y \le k\) 的形式,连边 \((y,x,k)\)

小套路:\(\frac {X}{Y} \le K\) 可以通过换底公式化成 \(log X - log Y \le log K\),例题见luoguP4926

模板

#include<bits/stdc++.h>
#define inf (0x3f3f3f3f)
using namespace std;
const int N=5e3+10;
int n,m;
int pre[N<<1],now[N<<1],to[N<<1],val[N<<1],tot;
bool vis[N];
int dis[N],cnt[N];
queue<int>q;
void add(int x,int y,int z){
	pre[++tot]=now[x];
	now[x]=tot;to[tot]=y;
	val[tot]=z;
}
bool spfa(int st){
	for(int i=0;i<=n;i++)
		dis[i]=inf,vis[i]=0,cnt[i]=0;
	dis[st]=0;vis[st]=true,q.push(st);
	while(q.size()){
		int u=q.front();q.pop();
		vis[u]=false;
		for(int i=now[u];i;i=pre[i]){
			int v=to[i],z=val[i];
			if(dis[v]>dis[u]+z){
				dis[v]=dis[u]+z;
				cnt[v]=cnt[u]+1;
				if(cnt[u]>=n)return false;
				if(!vis[v]){
					vis[v]=true;
					q.push(v);
				}
			}
		}
	}
	return true;
}
void print(){
	for(int i=1;i<=n;i++)
		printf("%d ",dis[i]);
	return;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(v,u,w);
	}	
	for(int i=1;i<=n;i++)
		add(0,i,0);
	int flag=spfa(0);
	if(!flag)puts("NO");
	else print(); 
	return 0;
} 
posted @ 2021-02-21 14:48  Isenthalpic  阅读(44)  评论(0编辑  收藏  举报