06年的题目还是比较简单的……为防止查一道题时其他题被剧透而将题解部分调成白色了……
有谁看懂了题求讲解……
代码:
超级英雄:
//BZOJ1191; Hero (HNOI2006); Bipartite Graph
#include
#include
#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
#include
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
#include
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
#include
#include
#include
#define S 50
#define N 50
#define INFI 12345678
typedef std::pair 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
#include
#include
#include
#include
#include
#include
#define N 12
#define LEN 50
typedef std::pair 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 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
#include
#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
#include
#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;
}