260806 康复性训练记录
情况
这次模拟赛只有三个题,把签到题去掉了。因为我太菜了,后面的三个模板题赛前都没做过。
总结一下:模板大赛能做不出 \(\frac23\) 也是挺厉害。
| # | A | B | C | D |
|---|---|---|---|---|
| S | - | 100 | 10 | 0 |
B
题目:P5340 [TJOI2019] 大中锋的游乐场
\(n\) 个点 \(m\) 条边的无向图中有 \(a\) 个 A 类点和 \(b\) 个 B 类点(\(a+b=n\)),给定了每个点的种类和两个点 \(s,t\),求 \(s\) 到 \(t\) 的最短路径,使得 \(s\) 到 \(t\) 的过程中 A 类点与 B 类点的数量之差任意时刻不能超过 \(k\)。
分层图最短路。跑一个 Dijkstra 就解决了,难度约等于 NOI 2025 D1T1 机器人。
简单来说,记路径上两类点数之差为 \(p\),对边进行松弛时有 \(dis[v][p_u+<type_v>]\leftarrow dis[u][p_u]+w\)。
给到普及+/提高(旧标准)。
#include <bits/stdc++.h>
using namespace std;
#define gc getchar
template<typename T> void read(T &x) {
char c = gc(); int f = 1; x = 0;
while (!isdigit(c)) f = (c == '-' ? -f : f), c = gc();
while (isdigit(c)) x = (x << 3) + (x << 1) + c - '0', c = gc();
x *= f;
}
template<typename T, typename ... Args> void read(T &x, Args& ... args) {read(x); read(args...);}
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define lll __int128
#define rep(i, s, t) for(ll i=(s);i<=(t);i++)
#define per(i, s, t) for(ll i=(s);i>=(t);i--)
template<typename T> void chkmx(T &x, const T &y) {x = max(x, y);}
template<typename T> void chkmn(T &x, const T &y) {x = min(x, y);}
const ll N = 10005, bis = 15;
ll n, m, k, s, t, a[N], dis[N][30], vis[N][30];
struct edge {
ll to, w;
};
vector<edge> g[N];
struct node {
ll v, k, w;
};
const bool operator <(const node &x, const node &y) {return x.w > y.w;}
priority_queue<node> q;
void dijkstra(int st) {
dis[st][bis + a[st]] = 0;
q.push({st, a[st], 0});
while (!q.empty()) {
auto [u, val, l] = q.top();
q.pop();
if (vis[u][bis + val]) continue;
vis[u][val] = 1;
// cout << u << ' ' << val << ' ' << l << '\n';
for (auto [v, w] : g[u]) {
// cout << u << ":" << v << '\n';
if (a[v] + val <= k && a[v] + val >= -k) {
// cout << u << ">" << v << '\n';
if (dis[v][bis + val + a[v]] > dis[u][bis + val] + w) {
// cout << u << "->" << v << '\n';
dis[v][bis + val + a[v]] = dis[u][bis + val] + w;
q.push({v, val + a[v], dis[v][bis + val + a[v]]});
}
}
}
}
}
void pd() {
read(n, m, k);
rep(i, 1, n) g[i].clear();
rep(i, 1, n) {
read(a[i]);
a[i] = (a[i] == 2) ? 1 : -1;
}
rep(i, 1, m) {
int u, v, w;
read(u, v, w);
g[u].push_back({v, w});
g[v].push_back({u, w});
}
read(s, t);
rep(i, 1, n) rep(j, 0, 29) dis[i][j] = 1e18, vis[i][j] = 0;
dijkstra(s);
ll ans = 1e18;
rep(j, 0, 29) ans = min(ans, dis[t][j]);
if (ans < 1e17) printf("%lld\n", ans);
else printf("-1\n");
}
int main() {
int _; read(_); while (_--)
pd();
return 0;
}
C
题目:P4111 [HEOI2015] 小 Z 的房间
有 \(n\times m\) 的网格图,一开始没有连边。你需要上下左右连边,使得除输入给出的禁止连边的点外,网格图形成一棵树。求连边方案数 \(\mod 1000000000\)。
这道题是矩阵树定理的模板题,这是一种可以用于求无/有向图生成树数量的算法。具体请查阅 OI-Wiki 等互联网公开资料。唯一需要注意的是,本题的“墙”(不能连边的点)不要给点赋编号,或者将此类点连接或仅连接到某个固定的点(如 \((1,1)\)),防止因为孤立点导致生成树计数为 \(0\)。
涉及到省选/NOI−的知识点。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 605, mod = 1e9;
int n, a[N][N];
int m;
char c[N][N];
int dir[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
long long Gauss(int n){
long long ans = 1;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
while (a[j][i]) {
long long t = a[i][i] / a[j][i];
for (int k = i; k <= n; k++) a[i][k] = (a[i][k] - t * a[j][k] % mod + mod) % mod;
swap(a[i], a[j]);
ans = -ans;
}
}
ans = (ans * a[i][i] % mod + mod) % mod;
}
return ans;
}
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
c[i][j] = getchar();
while (c[i][j] != '.' && c[i][j] != '*') c[i][j] = getchar();
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (c[i][j] == '*') {
int u = (i - 1) * m + j;
int v = (1 - 1) * m + 1;
a[u][v] = (a[u][v] - 1) % mod;
a[v][u] = (a[v][u] - 1) % mod;
a[v][v] = (a[v][v] + 1) % mod;
a[u][u] = (a[u][u] + 1) % mod;
continue;
}
for (int k = 0; k <= 3; k++) {
int ni = i + dir[k][0], nj = j + dir[k][1];
if (ni <= n && ni >= 1 && nj <= m && nj >= 1) {
if (c[ni][nj] == '*') continue;
int u = (i - 1) * m + j;
int v = (ni - 1) * m + nj;
a[u][v] = (a[u][v] - 1) % mod;
// a[v][u] = (a[v][u] - 1) % mod;
// a[v][v] = (a[v][v] + 1) % mod;
a[u][u] = (a[u][u] + 1) % mod;
}
}
}
}
n = (n - 1) * m + m - 1;
cout << Gauss(n) << '\n';
return 0;
}
D
题目:P3733 [HAOI2017] 八纵八横
详见稍后发布的解题报告。
本文来自博客园,作者:cwkapn,转载请注明原文链接:https://www.cnblogs.com/cwkapn/p/22277355


浙公网安备 33010602011771号