差分约束
(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;
}

浙公网安备 33010602011771号