专题 差分约束 + 优化建图
1.矩阵估价


solution:这个题并不难,重要的是它代表了一种思想,即差分约束只能解决a-b>p的问题,但是我们通过对h,a,b取log,将乘除法转化为了加减法,这个思想非常重要,下面贴个码。
#include <bits/stdc++.h> using namespace std; struct node { int to, nxt; double len; }e[1000000]; int n, m, x, y, vis[500005], head[500005], cnt[500005], tot, h[405][405]; double dis[500005]; inline void add_e(int u, int v, double w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;} bool spfa() { queue <int> Q; for (int i = 0; i <= n + m; i++) dis[i] = 1e9; memset(cnt, 0, sizeof cnt); memset(vis, 0, sizeof vis); Q.push(0); dis[0] = 0; while (!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = 0; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (dis[v] > dis[u] + e[i].len) { dis[v] = dis[u] + e[i].len; if (++cnt[v] > n + m) return 0; if (!vis[v]) vis[v] = 1, Q.push(v); } } } return 1; } void solve() { memset(head, 0, sizeof head); tot = 0; scanf("%d%d%d%d", &n, &m, &x, &y); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) scanf("%d", &h[i][j]); double xx = log2(x), yy = log2(y); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { double hh = log2(h[i][j]); add_e(i, j + n, hh - xx); add_e(j + n, i, yy - hh); } } for (int i = 1; i <= n + m; i++) add_e(0, i, 0); if (spfa()) puts("YES"); else puts("NO"); } int main() { int t; scanf("%d", &t); while (t--) solve(); }
2.最省路费


solution:异或优化建图经典题目,大体的思路就是将i与(i ^ 1<<j)连边,边权为j*c来将边数优化到nlogn的级别,下面贴个码。
#pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; typedef pair <int, int> P; struct node { int to, nxt, len; }e[8000005]; int head[4000005], tot, dis[4000005]; bool vis[4000005]; inline void add_e(int u, int v, int w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;} void dijkstra(int s) { priority_queue <P, vector <P>, greater <P> > Q; memset(dis, 0x3f, sizeof dis); dis[s] = 0; Q.push(make_pair(0, s)); while (!Q.empty()) { int u = Q.top().second; Q.pop(); if (vis[u]) continue; else vis[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (!vis[v] && dis[v] > dis[u] + e[i].len) { dis[v] = dis[u] + e[i].len; Q.push(make_pair(dis[v], v)); } } } } char buf[1 << 22], *p1 = buf, *p2 = buf; #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++) template <class T> inline void rd(T &a) { char ch = getchar(); int x = 0, f = 1; while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();} while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar(); a = x * f; } int main() { int n, m, c; rd(n), rd(m), rd(c); for (int i = 1, x, y, z; i <= m; i++) { rd(x), rd(y), rd(z); add_e(x, y, z); } int s, t; rd(s), rd(t); for (int i = 0; i <= n; i++) for (int j = 1; j <= n; j <<= 1) if ((i ^ j) <= n) add_e(i, i ^ j, j * c); dijkstra(s); printf("%d", dis[t]); }
3.遗留


solution:线段树优化建图板题,不多说了,下面贴个码。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair <ll, ll> P; #define mid (Tree[q].l + Tree[q].r >> 1) struct node { int l, r; }; node Tree[3000005]; int cnt = 1, ls[3000005], rs[3000005]; ll num[3000005][2]; struct Edge { int to, nxt; ll len; }e[3000005]; int head[3000005]; ll dis[3000005], tot, n, q, k, s; bool vis[3000005]; inline void add_e(int u, int v, ll w) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot; e[tot].len = w;} void Build(int q, int x, int y, int tp) { Tree[q].l = x, Tree[q].r = y; // printf("%d %d %d %d\n", q, tp, Tree[q].l, Tree[q].r); if (x < y) { ls[q] = ++cnt; Build(ls[q], x, mid, tp); !tp ? add_e(q, ls[q], 0) : add_e(ls[q], q, 0); rs[q] = ++cnt; Build(rs[q], mid + 1, y, tp); !tp ? add_e(q, rs[q], 0) : add_e(rs[q], q, 0); } else num[x][tp] = cnt; } void modify1(int q, int v, int x, int y, int z) { if (Tree[q].l > y || Tree[q].r < x) return; if (Tree[q].l >= x && Tree[q].r <= y) { add_e(num[v][1], q, z); return; } modify1(ls[q], v, x, y, z); modify1(rs[q], v, x, y, z); } void modify2(int q, int v, int x, int y, int z) { if (Tree[q].l > y || Tree[q].r < x) return; if (Tree[q].l >= x && Tree[q].r <= y) { add_e(q, num[v][0], z); return; } modify2(ls[q], v, x, y, z); modify2(rs[q], v, x, y, z); } void dijkstra(int s) { priority_queue <P, vector <P>, greater <P> > Q; memset(dis, 0x3f, sizeof dis); dis[s] = 0; Q.push(make_pair(0, s)); while (!Q.empty()) { ll u = Q.top().second; Q.pop(); if (vis[u]) continue; vis[u] = 1; for (ll i = head[u]; i; i = e[i].nxt) { ll v = e[i].to; if (!vis[v] && dis[v] > dis[u] + e[i].len) { dis[v] = dis[u] + e[i].len; Q.push(make_pair(dis[v], v)); } } } } main() { scanf("%lld%lld%lld", &n, &q, &s); Build(1, 1, n, 0); k = ++cnt; Build(cnt, 1, n, 1); for (ll i = 1; i <= n; i++) add_e(num[i][0], num[i][1], 0), add_e(num[i][1], num[i][0], 0); for (ll i = 1, tp, x, y, z, l, r; i <= q; i++) { scanf("%lld", &tp); if (tp == 1) scanf("%lld%lld%lld", &x, &y, &z), add_e(num[x][1], num[y][0], z); if (tp == 2) scanf("%lld%lld%lld%lld", &x, &l, &r, &z), modify1(1, x, l, r, z); if (tp == 3) scanf("%lld%lld%lld%lld", &x, &l, &r, &z), modify2(k, x, l, r, z); } dijkstra(num[s][1]); for (ll i = 1; i <= n; i++) printf("%lld ", dis[num[i][0]] >= 0x3f3f3f3f3f3f3f ? -1 : dis[num[i][0]]); // for (ll i = 1; i <= cnt; i++) // { // for (ll j = head[i]; j; j = e[j].nxt) // { // printf("***%d %d %d %d\n", i, e[j].to, e[j].len, j); // } // } }

浙公网安备 33010602011771号