差分约束

差分约束

建图套路:

\(B-A\le c\ \rightarrow dis[B]\le dis[A]+c\) 那么可以类比 \(spfa\) 的更新方式 从 \(A\)\(B\) 连一条边权为 \(c\) 的边即可

对于 \(B=A\) 的条件 可以类比为 \(B-A\le0\)\(A-B\le0\) 那么从 \(A\)\(B\)\(0\) 边 同时反向连 \(0\) 边即可

最后看有没有负环 负环就是无解情况

P1993 小 K 的农场

判断负环还是需要用判断最短路条数的写法...否则就寄了

注意我们建立了一个超级源点来保证图连通 那么我们判断负环的时候需要判断 \(cnt[v]=n+1\) 而不是 \(n\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define mid (l+r>>1)
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
const int N = 5e3 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
char buf[1<<24] , *p1 , *p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
// #define getchar() cin.get();
int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f ;
}

int n , m , cnt[N] , in[N] , dis[N] , s;
int q[10000000] , head = 1 , tail;

vector<pii> e[N];
inl void add ( int u , int v , int w ) { e[u].eb(v,w); }

int spfa()
{
	memset ( dis , inf , sizeof dis );
	dis[s] = 0 , in[s] = 1 , q[++tail] = s;
	while ( head <= tail )
	{
		int u = q[head++]; in[u] = 0;
		for ( auto [v,w] : e[u] )
			if ( dis[v] > dis[u] + w )
			{
				dis[v] = dis[u] + w;
				cnt[v] = cnt[u] + 1;
				if ( cnt[v] >= n + 1 ) return 0;
				if ( !in[v] ) q[++tail] = v , in[v] = 1;
			}
	}
	return 1;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ ) add ( s , i , 0 );
	for ( int i = 1 ; i <= m ; i ++ )
	{	
		int op = read() , u = read() , v = read() , w;
		if ( op == 1 ) w = read() , add ( u , v , -w );
		if ( op == 2 ) w = read() , add ( v , u , w );
		if ( op == 3 ) add ( u , v , 0 ) , add ( v , u , 0 );
	}
	cout << ( spfa() == 0 ? "No" : "Yes" ) << endl;
	return 0;	
}

P5960 【模板】差分约束

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
#define int long long
const int N = 5e3 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;

int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
} 

int n , m , dis[N] , in[N] , cnt[N];

vector<pii> e[N];
inl void add ( int u , int v , int w ) { e[u].eb(v,w); }

queue<int> q;

int spfa ( int s )
{
	memset ( dis , inf , sizeof dis );
	q.push(s) , in[s] = 1 , dis[s] = 0;
	while ( !q.empty() )
	{
		int u = q.front(); q.pop(); in[u] = 0;
		for ( auto p : e[u] )
		{
			int v = p.fi , w = p.se;
			if ( dis[v] > dis[u] + w ) 
			{
				dis[v] = dis[u] + w , cnt[v] = cnt[u] + 1;
				if ( cnt[v] >= n + 1 ) return 0;
				if ( !in[v] ) q.push(v) , in[v] = 1;
			}
		}
	}
	return 1;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	n = read() , m = read();
	for ( int i = 1 ; i <= n ; i ++ ) add ( 0 , i , 0 );
	for ( int i = 1 , u , v , w ; i <= m ; i ++ ) u = read() , v = read() , w = read() , add ( v , u , w );
	if ( !spfa(0) ) return cout << "NO" << endl , 0;
	for ( int i = 1 ; i <= n ; i ++ ) cout << dis[i] << ' ';
	return 0;
}
posted @ 2023-09-02 21:07  Echo_Long  阅读(5)  评论(0编辑  收藏  举报