Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P4294 [WC2008]游览计划

P4294 [WC2008]游览计划

将一般斯坦纳树的边权换成点权。考虑记录 pair $pre _ {t, s}$ 表示上一个状态,回溯找到答案即可。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <cstdio>
#include <queue>
#include <vector>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
template <class Type>
void read (Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
c == '-' && (flag = true);
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0';
flag && (x = ~x + 1);
}
template <class Type, class ...rest>
void read (Type &x, rest &...y) { read(x), read(y...); }
template <class Type>
void write (Type x)
{
x < 0 && (putchar('-'), x = ~x + 1);
x > 9 && (write(x / 10), 0);
putchar('0' + x % 10);
}
typedef pair <int, int> PII;
const int N = 110, M = 510, K = 10, inf = 1e9;
const int dx[] = { 0, 1, -1, 0 }, dy[] = { 1, 0, 0, -1 };
bool vis[N];
vector <int> g[N];
PII pre[N][1 << K];
int n, m, k, rt, w[N], ans[N], f[N][1 << K];
bool inside (int a, int b) { return a > 0 && b > 0 && a <= n && b <= m; }
int id (int a, int b) { return (a - 1) * m + b; }
void dfs (int t, int s)
{
if (!pre[t][s].se) return;
ans[t] = true;
if (pre[t][s].fi == t) dfs(t, s ^ pre[t][s].se);
dfs(pre[t][s].fi, pre[t][s].se);
}
int main ()
{
read(n, m);
for (int i = 1; i <= n * m; ++i)
for (int j = 0; j < 1 << K; ++j) f[i][j] = inf;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
{
int t = id(i, j);
read(w[t]);
if (!w[t]) f[rt = t][1 << k++] = 0;
for (int d = 0; d < 4; ++d)
{
int nx = i + dx[d], ny = j + dy[d];
if (inside(nx, ny)) g[t].pb(id(nx, ny));
}
}
for (int s = 1; s < 1 << k; ++s)
{
priority_queue <PII, vector <PII> , greater <PII> > q;
for (int i = 1; i <= n * m; ++i) vis[i] = false;
for (int i = 1; i <= n * m; ++i)
{
for (int t = s; t; --t &= s)
if (f[i][t] + f[i][s ^ t] - w[i] < f[i][s])
{
f[i][s] = f[i][t] + f[i][s ^ t] - w[i];
pre[i][s] = mp(i, t);
}
if (f[i][s] ^ inf) q.push(mp(f[i][s], i));
}
while (!q.empty())
{
int t = q.top().se; q.pop();
if (vis[t]) continue;
vis[t] = true;
for (int i : g[t])
if (f[t][s] + w[i] < f[i][s])
{
f[i][s] = f[t][s] + w[i];
pre[i][s] = mp(t, s);
q.push(mp(f[i][s], i));
}
}
}
write(f[rt][(1 << k) - 1]), puts("");
dfs(rt, (1 << k) - 1);
for (int i = 1; i <= n; ++i, puts(""))
for (int j = 1; j <= m; ++j, putchar(' '))
{
int t = id(i, j);
putchar(!w[t] ? 'x' : (ans[t] ? 'o' : '_'));
}
return 0;
}