差分约束

(1)如何求不等式组的可行解

对于x <= y + c可以建立一条从y - > x边权为c的边,则在最短路中一定有dis[x] <= dis[y] + c,所以差分约束就可以转化为图论中的最短路问题。

源点需要满足的条件:从源点出发一定可以走到所有的边。

步骤:

[1]将不等式转化成边。

[2]找一个超级源点,使得该源点可以遍历到所有的边。

[3]从源点求一遍单元最短路。

结果:
[1]存在负环,原不等式组一定无解。

不等式组无解等价于原图有负环,因为会推出x <= x + c(c < 0)是矛盾的。

[2]不存在负环,dis[i]就是原不等式组的一组可行解。

(2)如何求最大值或者最小值(指的是每个变量的最值)

结论:如果求的是最小值,应该用最长路;如果求的是最大值,应该用最短路。

问题1:如何转化x <= c这类的不等式:

方法:建立一个超级源点0,然后建立0 -> i长度为c的边即可。

求最大值是用最短路(上界里面的最小),求最小值是用最长路(下界里面的最大)。

糖果

首先,快读;其次,spfa负环判断优化;最后领接表改成链式前向星——>终于没有超时了!spfa真是一门玄学。

#include <bits/stdc++.h>
using namespace std;
const int N = 1000005;
int n, dis[N], k, cnt[N], vis[N], nxt[N], head[N], to[N], tot = 0, w[N];
struct edge
{
	int v, w;
};
int read()
{
	int x = 0;
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x;
}
void add(int u, int v, int W)
{
	to[++ tot] = v, nxt[tot] = head[u], w[tot] = W, head[u] = tot;
	return ;
}

int q[N], hh = 0;
bool spfa_max_long()
{
	q[++ hh] = 0;
	memset(dis, -0x3f, sizeof(dis));
	vis[0] = 1, cnt[0] = 0, dis[0] = 0;
	while(hh)
	{
		int x = q[hh --];
		vis[x] = 0;
		if(cnt[x] >= n + 1) return false;
		for (int i = head[x]; i; i = nxt[i])
		{
			int y = to[i];
			if(dis[y] < dis[x] + w[i]) 
			{
				dis[y] = dis[x] + w[i];
				cnt[y] = cnt[x] + 1;
				if(!vis[y]) q[++ hh] = y, vis[y] = 1;
			}
		}
	}
	return true;
}
int main()
{
	n = read(), k = read();
	for (int i = 1; i <= n; ++ i) add(0, i, 1);
	for (int i = 1; i <= k; ++ i)
	{
		int x, a, b;
		x = read(), a = read(), b = read();
		if(x == 1) add(a, b, 0), add(b, a, 0);
		else if(x == 2) add(a, b, 1);
		else if(x == 3) add(b, a, 0);
		else if(x == 4) add(b, a, 1);
		else if(x == 5) add(a, b, 0);
 	}
 	if(spfa_max_long())
 	{
 		long long sum = 0;
		for (int i = 1; i <= n; ++ i) sum = sum + dis[i];
		printf("%lld", sum);	
	}
	else printf("-1");
 	return 0;
}

幸运数字

https://www.becoder.com.cn/article/16046

#include <bits/stdc++.h>
using namespace std;
const int N = 100005, inf = 100000000, M = 800005;
int dis1[N], dis2[N], vis[N], cnt[N], n, m, tot = 0;
struct node
{
	int l, r, k;
}p[N << 1];
struct edge
{
	int nxt, to, w;
}e[M];
int head[N];
void add(int u, int v, int w)
{
	e[++ tot].nxt = head[u], e[tot].to = v, e[tot].w = w, head[u] = tot;
	return ;
}
int read()
{
	int x = 0; char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x;
}
queue<int> q;
void spfa_min()
{
	for (int i = 0; i <= n; ++ i) vis[i] = 0, dis1[i] = inf, cnt[i] = 0;
	vis[0] = 1, q.push(0), dis1[0] = 0;
	for (int i = 1; i <= n; ++ i) add(i, i - 1, 0), add(i - 1, i, 1);
	for (int i = 1; i <= m; ++ i)
	{
		add(p[i].l - 1, p[i].r, p[i].k);
		add(p[i].r, p[i].l - 1, - p[i].k);
	}
	while(!q.empty())
	{
		int x = q.front(); q.pop();
		vis[x] = 0;
		for (int i = head[x]; i; i = e[i].nxt)
		{
			int y = e[i].to;
			if(dis1[y] > dis1[x] + e[i].w)
			{
				dis1[y] = dis1[x] + e[i].w;
				cnt[y] = cnt[x] + 1;
				if(!vis[y]) q.push(y), vis[y] = 1;
			}
		}
	}
}
void spfa_max()
{
	tot = 0;
	memset(head, 0, sizeof(head));
	for (int i = 0; i <= n; ++ i) vis[i] = 0, dis2[i] = -inf, cnt[i] = 0;
	vis[0] = 1, q.push(0), dis2[0] = 0;
	for (int i = 1; i <= n; ++ i) add(i - 1, i, 0), add(i, i - 1, - 1);
	for (int i = 1; i <= m; ++ i)
	{
		add(p[i].r, p[i].l - 1, - p[i].k);
		add(p[i].l - 1, p[i].r, p[i].k);
	} 
	while(!q.empty())
	{
		int x = q.front(); q.pop();
		vis[x] = 0;
		for (int i = head[x]; i; i = e[i].nxt)
		{
			int y = e[i].to;
			if(dis2[y] < dis2[x] + e[i].w)
			{
				dis2[y] = dis2[x] + e[i].w;
				cnt[y] = cnt[x] + 1;
				if(!vis[y]) q.push(y), vis[y] = 1;
			}
		}
	 } 
}
int main()
{
	n = read(), m = read();
	for (int i = 1; i <= m; ++ i) p[i].l = read(), p[i].r = read(), p[i].k = read();
	spfa_min();
	spfa_max();
	for (int i = dis2[n]; i <= dis1[n]; ++ i) printf("%d ", i);
	return 0;
}
posted @ 2025-02-13 10:31  Helioca  阅读(14)  评论(0)    收藏  举报
Document