算法随笔——图论之差分约束

求不等式组的最大解和最小解:
神奇结论:求最大解跑最短路,求最小解跑最长路
设超级源点为 x0,x0 到其他点边权为 W
则跑最短路时,答案为 x1,x2...xn<=w 的最大解。
跑最长路时,答案为 x1,x2...xn>=w 的最小解。

感性理解一下还挺对的。
例题:[ABC216G] 01Sequence

一些相关的最短路基础知识:
spfa时间复杂度 O(nm)
dijstra 不能求解负权图,也不能求最长路。
而 spfa可以。
spfa 可以求负环,当一个点被松弛超过n次,则该图存在负环。
模板代码:

点击查看代码
// Problem: P3385 【模板】负环
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3385
// Memory Limit: 250 MB
// Time Limit: 2000 ms
// Author: Eason
// Date:2024-06-20 23:38:48
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define re register
#define PII pair<int,int>
int read()
{
	int f=1,k=0;char c = getchar();
	while(c <'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')k=(k<<1)+(k<<3)+(c^48),c=getchar();
	return k*f;
}

const int N = 3e3+5;

int t,n,m;
vector<PII> v[N];
int dis[N],vis[N];
int cnt[N];
bool spfa()
{
	memset(dis,INF,sizeof dis);
	memset(vis,0,sizeof vis);
	memset(cnt,0,sizeof cnt);
	queue<int> q;
	q.push(1);vis[1] = 1,dis[1] = 0;
	while (q.size())
	{
		int u = q.front();q.pop();vis[u] = 0;
		for (auto &[j,c] : v[u])
		{
		
			if (dis[j] > dis[u] + c)
			{
			
				dis[j] = dis[u] + c;
				if (!vis[j]) vis[j] = 1,q.push(j);
				if (++cnt[j] > n) return 0;
			}
			
		}
		
	}
	return 1;
}

void add(int a,int b,int c)
{
	v[a].push_back({b,c});
}

int main()
{
	cin >> t ;
	while (t--)
	{
		
		cin >> n >> m;
		for (int i = 1;i <= m;i++) 
		{
			int x = read(),y = read(),w = read();
			if (w >= 0) add(x,y,w),add(y,x,w);
			else add(x,y,w);
		}
		if (spfa()) puts("NO");
		else puts("YES");
		for (int i = 1;i <= n;i++) v[i].clear();
	}
	return 0;
}
posted @   codwarm  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略
点击右上角即可分享
微信分享提示