0411周赛
T1:NOIP2016 车站分级
思路:拓扑排序,注意建虚拟源点。
#include <bits/stdc++.h> using namespace std; struct node { int to, nxt; }e[2000005]; int n, m, head[1000005], ind[1000005], tot, f[1000005], hi[1000005], lw[1000005], dis[1000005]; bool vis[1000005]; inline void add_e(int u, int v) {e[++tot].to = v; e[tot].nxt = head[u]; head[u] = tot;} void dfs(int u) { if (f[u]) return; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; dfs(v); f[u] = max(f[u], f[v] + 1); } f[u] -= (u > n); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { memset(vis, 0, sizeof vis); int t, k = 0; scanf("%d", &t); for (int j = 1, x; j <= t; j++) scanf("%d", &hi[j]), vis[hi[j]] = 1, add_e(n + i, hi[j]); for (int j = hi[1]; j <= hi[t]; j++) if (!vis[j]) add_e(j, n + i); } int ans = 0; for (int i = 1; i <= n; i++) if (!ind[i]) dfs(i); for (int i = 1; i <= n; i++) ans = max(ans, f[i]); printf("%d", ++ans); }
T2:矩形操作

思路:差分约束,把每一行和每一列当作一个点,x+y=z转化为x-(-y)=z。
#include <bits/stdc++.h> using namespace std; struct node { int to, nxt, len; }e[2000005]; int n, m, k, head[1000005], tot, dis[1000005], cnt[1000005]; bool vis[1000005]; 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;} bool spfa() { queue <int> Q; memset(dis, 0x3f, sizeof dis); 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] > 2 * n) return 0; if (!vis[v]) vis[v] = 1, Q.push(v); } } } return 1; } int main() { int t; scanf("%d", &t); while (t--) { memset(head, 0, sizeof head); tot = 0; scanf("%d%d%d", &n, &m, &k); if (n <= m) swap(m, n); for (int i = 1, x, y, z; i <= k; i++) scanf("%d%d%d", &x, &y, &z), add_e(y + n, x, z), add_e(x, y + n, -z); for (int i = 1; i <= 2 * n; i++) add_e(0, i, 0); if (spfa()) puts("Yes"); else puts("No"); } }
T3:矩阵估价

思路:讲道理这题属实yin间,居然要取log把除法转化为减法,于是又成了差分约束,建边方法和T2类似。
#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(); }
T4:海岛旅游

思路:首先bfs或dfs搜出来一个个岛屿,然后最短路求两两岛屿的距离,最后状压dp解决。(讲道理这个题也很yin间)
#include <bits/stdc++.h> using namespace std; typedef pair <int, int> P; int dx[4] = {-1, 0, 1, 0}; int dy[4] = {0, -1, 0, 1}; int pos[2505], cnt; char ch[55][55]; int head[250005], n, m, dis[55][55], d[55][55], f[55][(1 << 15) + 1], bl[55][55]; bool vis[55][55]; bool check(int x, int y) {return x >= 1 && x <= n && y >= 1 && y <= m;} vector <int> xx[250005]; vector <int> yy[250005]; void bfs(int sx, int sy) { queue <P> Q; Q.push(make_pair(sx, sy)); vis[sx][sy] = 1, bl[sx][sy] = cnt; xx[cnt].push_back(sx); yy[cnt].push_back(sy); while (!Q.empty()) { int x = Q.front().first, y = Q.front().second; Q.pop(); for (int i = 0; i < 4; i++) { int fx = x + dx[i], fy = y + dy[i]; if (check(fx, fy) && !vis[fx][fy] && ch[fx][fy] == 'X') { Q.push(make_pair(fx, fy)); bl[fx][fy] = cnt; xx[cnt].push_back(fx); yy[cnt].push_back(fy); vis[fx][fy] = 1; } } } } void spfa(int s) { queue <P> Q; memset(vis, 0, sizeof vis); memset(d, 0x3f, sizeof d); int num = xx[s].size(); for (int i = 0; i < num; i++) { int x = xx[s][i], y = yy[s][i]; vis[x][y] = 1, d[x][y] = 0; Q.push(make_pair(x, y)); } while (!Q.empty()) { int x = Q.front().first, y = Q.front().second; Q.pop(); vis[x][y] = 0; for (int i = 0; i < 4; i++) { int fx = x + dx[i], fy = y + dy[i]; if (check(fx, fy) && ch[fx][fy] != '.') { if (ch[fx][fy] == 'S') { if (d[fx][fy] > d[x][y] + 1) { d[fx][fy] = d[x][y] + 1; if (!vis[fx][fy]) { vis[fx][fy] = 1; Q.push(make_pair(fx, fy)); } } } else if (ch[fx][fy] == 'X') { if (d[fx][fy] > d[x][y]) { d[fx][fy] = d[x][y]; if (!vis[fx][fy]) { vis[fx][fy] = 1; Q.push(make_pair(fx, fy)); } } dis[s][bl[fx][fy]] = dis[bl[fx][fy]][s] = min(dis[s][bl[fx][fy]], d[fx][fy]); } } } } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%s", ch[i] + 1); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (!vis[i][j] && ch[i][j] == 'X') ++cnt, bfs(i, j); memset(dis, 0x3f, sizeof dis); for (int i = 1; i <= cnt; i++) dis[i][i] = 0, spfa(i); memset(f, 0x3f, sizeof f); int all = (1 << cnt) - 1, ans = 0x3f3f3f3f; for (int i = 1; i <= cnt; i++) f[i][(1 << i - 1)] = 0; for (int s = 1; s <= all; s++) { for (int i = 1; i <= cnt; i++) { if (s & (1 << i - 1)) { for (int j = 1; j <= cnt; j++) { if (s & (1 << j - 1)) continue; f[j][s | (1 << j - 1)] = min(f[j][s | (1 << j - 1)], dis[i][j] + f[i][s]); } } } } for (int i = 1; i <= cnt; i++) ans = min(ans, f[i][all]); printf("%d", ans); }
T5:最省路费

思路:异或优化建图板题,可惜当时我不会。
#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]); }

浙公网安备 33010602011771号