06年的题目还是比较简单的……为防止查一道题时其他题被剧透而将题解部分调成白色了……
有谁看懂了题求讲解……
代码:
超级英雄:
//BZOJ1191; Hero (HNOI2006); Bipartite Graph #include <cstdio> #include <cstdlib> #define N 1000 #define M 1000 struct edge { int next, node; }e[M << 1 | 1]; int n, m, x, y, head[N + 1], tot = 0, match[N + 1], ans = 0; bool v[N + 1]; inline void addedge(int a, int b) { e[++tot].next = head[a]; head[a] = tot, e[tot].node = b; } bool find(int x) { for (int i = head[x]; i; i = e[i].next) { int node = e[i].node; if (v[node]) continue; v[node] = true; if (!match[node] || find(match[node])) { match[node] = x; return true; } } return false; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; ++i) { scanf("%d%d", &x, &y); ++x, ++y; addedge(i, x), addedge(i, y); } for (int i = 1; !ans && i <= m; ++i) { for (int j = 1; j <= n; ++j) v[j] = false; if (!find(i)) ans = i; } ans = !ans ? m : ans - 1; printf("%d\n", ans); return 0; }
//BZOJ1192; 鬼谷子的钱袋 (HNOI2006); #include <cstdio> #include <cstdlib> typedef long long ll; ll n, x = 1LL; int ans = 0; int main() { scanf("%lld", &n); while (x < n) x <<= 1LL, ++ans; printf("%d\n", ans); }
//BZOJ1193; 马步距离; Observation #include <cstdio> #include <cstdlib> int x1, x2, y1_, y2, d, ans; int abs(int x) { return x < 0 ? -x : x; } int main() { scanf("%d%d%d%d", &x1, &y1_, &x2, &y2); d = abs(x1 - x2) + abs(y1_ - y2); for (ans = 0; ; ++ans) { if (((x1 + y1_ & 1) ^ (x2 + y2 & 1)) != (ans & 1)) continue; if (d <= ans * 3 && abs(x1 - x2) <= ans * 2 && abs(y1_ - y2) <= ans * 2) break; } if (d == 1) ans = 3; if (d == 4 && abs(x1 - x2) == 2 && abs(y1_ - y2) == 2) ans = 4; printf("%d\n", ans); return 0; }
//BZOJ1194; Pandora (HNOI2006); #include <cstdio> #include <cstdlib> #include <utility> #include <algorithm> #define S 50 #define N 50 #define INFI 12345678 typedef std::pair<int, int> pair; #define pair(x, y) std::make_pair(x, y) int s, n[N + 1], m[N + 1], p[S + 1][N + 1][2], x, y, ans = 0; int cnt[N + 1], f[N + 1], ind[N + 1], v[N + 1][N + 1], ct = 0, Q[N + 1], h, t; bool con[N + 1][N + 1], out[N + 1][N + 1]; pair cur, q[N * N + 1]; inline bool check(int a, int b) { ++ct; h = t = 0; q[t++] = pair(0, 0); while (h < t) { cur = q[h++]; if (out[a][cur.first] && !out[b][cur.second]) return false; x = p[a][cur.first][0], y = p[b][cur.second][0]; if (v[x][y] != ct) v[x][y] = ct, q[t++] = pair(x, y); x = p[a][cur.first][1], y = p[b][cur.second][1]; if (v[x][y] != ct) v[x][y] = ct, q[t++] = pair(x, y); } return true; } int main() { scanf("%d", &s); for (int i = 1; i <= s; ++i) { scanf("%d%d", n + i, m + i); for (int j = 1; j <= m[i]; ++j) { scanf("%d", &x); out[i][x] = true; } for (int j = 0; j < n[i]; ++j) scanf("%d%d", &p[i][j][0], &p[i][j][1]); } for (int i = 1; i <= s; ++i) for (int j = 1; j <= s; ++j) if (i != j && check(i, j)) con[i][j] = 1; for (int i = 1; i <= s; ++i) cnt[i] = 1; for (int i = 1; i <= s; ++i) for (int j = 1; j < i; ++j) if (cnt[j] && con[i][j] && con[j][i]) { ++cnt[j], cnt[i] = 0; break; } for (int i = 1; i <= s; ++i) for (int j = 1; j <= s; ++j) if (cnt[i] && cnt[j] && con[i][j]) ++ind[j]; for (int i = 1; i <= s; ++i) f[i] = cnt[i]; h = t = 0; for (int i = 1; i <= s; ++i) if (!ind[i] && cnt[i]) Q[t++] = i; while (h < t) { int cur = Q[h++]; for (int i = 1; i <= s; ++i) if (con[cur][i] && cnt[i] && ind[i]) { --ind[i]; f[i] = std::max(f[i], f[cur] + cnt[i]); if (!ind[i]) Q[t++] = i; } } for (int i = 1; i <= s; ++i) ans = std::max(ans, f[i]); printf("%d\n", ans); return 0; }
//BZOJ1195; 最短母串 (HNOI2006); State Compression DP #include <cstdio> #include <cstdlib> #include <cstring> #include <climits> #include <algorithm> #include <utility> #include <queue> #define N 12 #define LEN 50 typedef std::pair<int, int> pair; #define pair(x, y) std::make_pair(x, y) int n, l[N + 1], f[N + 1][1 << N], d[N + 1][N + 1], x, y, from[N + 1][1 << N]; int ans = INT_MAX, tq[N + 1], top; char s[N + 1][LEN + 1], ts[N + 1][LEN * N + 1], str[N + 1][1 << N][LEN * N + 1], tmp[LEN * N + 1]; bool inq[N + 1][1 << N]; std::queue<pair> q; pair cur; int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%s", s[i]); for (int i = 1; i < n; ++i) for (int j = i + 1; j <= n; ++j) if (strcmp(s[i], s[j]) > 0) { strcpy(s[0], s[i]); memset(s[i], 0, sizeof(char) * l[i]); strcpy(s[i], s[j]); memset(s[j], 0, sizeof(char) * l[j]); strcpy(s[j], s[0]); } for (int i = 1; i <= n; ++i) l[i] = (int)strlen(s[i]); for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) { if (i == j) continue; d[i][j] = l[i]; for (int k = std::max(0, l[i] - l[j]); k < l[i]; ++k) if (!strncmp(s[i] + k, s[j], std::min(l[i] - k, l[j]))) { d[i][j] = k; break; } } for (int i = 1; i <= n; ++i) f[i][1 << i - 1] = 0, q.push(pair(i, 1 << i - 1)), inq[i][1 << i - 1] = true; while (!q.empty()) { y = q.front().first, x = q.front().second; inq[y][x] = false; q.pop(); for (int i = 1; i <= n; ++i) if (!(x & (1 << i - 1))) { int nx = x | (1 << i - 1); if (!f[i][nx] || f[i][nx] > f[y][x] + d[y][i]) { f[i][nx] = f[y][x] + d[y][i]; from[i][nx] = y; strcpy(str[i][nx], str[y][x]); strncpy(str[i][nx] + f[y][x], s[y], d[y][i]); if (!inq[i][nx]) q.push(pair(i, nx)), inq[i][nx] = true; } else if (f[i][nx] == f[y][x] + d[y][i]) { strcpy(tmp, str[y][x]); strncpy(tmp + f[y][x], s[y], d[y][i]); tmp[f[y][x] + d[y][i] + 1] = 0; if (strcmp(tmp, str[i][nx]) < 0) strcpy(str[i][nx], tmp); } } } for (int i = 1; i <= n; ++i) if (f[i][(1 << n) - 1] + l[i] < ans) ans = f[i][(1 << n) - 1] + l[i], top = 1, tq[0] = i; else if (f[i][(1 << n) - 1] + l[i] == ans) tq[top++] = i; for (int i = 0; i < top; ++i) { strcpy(ts[i], str[tq[i]][(1 << n) - 1]); strcpy(ts[i] + f[tq[i]][(1 << n) - 1], s[tq[i]]); } x = 0; for (int i = 1; i < top; ++i) if (strcmp(ts[x], ts[i]) > 0) x = i; printf("%s\n", ts[x]); return 0; }
//BZOJ1196; road (HNOI2006); Kruskal + Dichtomization #include <cstdio> #include <cstdlib> #define N 10000 #define M 20000 #define MAX 30000 struct inedge { int a, b, w1, w2; }ie[M + 1]; int n, m, f[N + 1], k; int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); } inline bool check(int x) { int cnt = 0; for (int i = 1; i <= n; ++i) f[i] = i; for (int i = 1; cnt < n && i <= m; ++i) if (ie[i].w1 <= x && find(ie[i].a) != find(ie[i].b)) ++cnt, f[find(ie[i].a)] = find(ie[i].b); if (cnt < k) return false; for (int i = 1; cnt < n && i <= m; ++i) if (ie[i].w2 <= x && find(ie[i].a) != find(ie[i].b)) ++cnt, f[find(ie[i].a)] = find(ie[i].b); if (cnt >= n - 1) return true; return false; } int main() { scanf("%d%d%d", &n, &k, &m); for (int i = 1; i <= m; ++i) scanf("%d%d%d%d", &ie[i].a, &ie[i].b, &ie[i].w1, &ie[i].w2); int l = 1, r = MAX; while (l < r) { int mid = l + r >> 1; if (check(mid)) r = mid; else l = mid + 1; } printf("%d\n", l); return 0; }
//BZOJ1197; 花仙子的魔法 (HNOI2006); DP #include <cstdio> #include <cstdlib> #define N 15 #define M 100 typedef long long ll; int m, n; ll f[N + 1][M + 1]; int main() { scanf("%d%d", &m, &n); for (int i = 1; i <= m; ++i) f[1][i] = 2 * i; for (int i = 1; i <= n; ++i) f[i][1] = 2; for (int i = 2; i <= n; ++i) for (int j = 2; j <= m; ++j) f[i][j] = f[i - 1][j - 1] + f[i][j - 1]; printf("%lld\n", f[n][m]); return 0; }