【LG4294】[WC2008]游览计划

【LG4294】[WC2008]游览计划

题面

洛谷

bzoj

题解

斯坦纳树板子题。

斯坦纳树的总结先留个坑。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <queue> 
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    return w * data; 
} 
typedef pair<int, int> P; 
typedef pair<P, int> Pi;
#define fi first
#define se second
const int INF = 0x3f3f3f3f; 
int N, M, K, rt, f[105][1111], a[105], ans[15][15]; 
bool inq[105]; 
Pi pre[105][1111]; 
const int dx[] = {0, 0, -1, 1} ; 
const int dy[] = {1, -1, 0, 0} ; 
queue<P> que; 
bool check(P x) { return x.fi >= 0 && x.se >= 0 && x.fi < N && x.se < M; } 
#define num(u) (u.fi * M + u.se) 
void spfa(int o) {
    while (!que.empty()) {
        P x = que.front(); que.pop(); inq[num(x)] = 0; 
        for (int i = 0; i < 4; i++) {
            P v = make_pair(x.fi + dx[i], x.se + dy[i]); 
            int nx = num(x), nv = num(v); 
            if (check(v) && f[nv][o] > f[nx][o] + a[nv]) {
                f[nv][o] = f[nx][o] + a[nv]; 
                if (!inq[nv]) inq[nv] = 1, que.push(v); 
                pre[nv][o] = make_pair(x, o); 
            } 
        } 
    } 
}
void dfs(P x, int o) {
    if (!pre[num(x)][o].se) return ; 
    ans[x.fi][x.se] = 1; 
    int nx = num(x); 
    if (pre[nx][o].fi == x) dfs(x, o ^ pre[nx][o].se);
    dfs(pre[nx][o].fi, pre[nx][o].se);
} 
int main () {
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin); 
#endif 
    cin >> N >> M; 
    memset(f, 0x3f, sizeof(f)); 
    for (int i = 0, tot = 0; i < N; i++) {
        for (int j = 0; j < M; j++) { 
            cin >> a[tot]; 
            if (!a[tot]) f[tot][1 << (K++)] = 0, rt = tot; 
            ++tot; 
        } 
    }
    for (int o = 1; o < (1 << K); o++) {
        for (int i = 0; i < N * M; i++) {
            for (int s = o & (o - 1); s; s = o & (s - 1)) 
                if (f[i][o] > f[i][s] + f[i][o ^ s] - a[i]) {
                    f[i][o] = f[i][s] + f[i][o ^ s] - a[i];
                    pre[i][o] = make_pair(make_pair(i / M, i % M), s);
                } 
            if (f[i][o] < INF) que.push(make_pair(i / M, i % M)), inq[i] = 1;
        }
        spfa(o);
    }
    cout << f[rt][(1 << K) - 1] << endl; 
    dfs(make_pair(rt / M, rt % M), (1 << K) - 1);
    for (int i = 0, tot = 0; i < N; i++){
        for (int j = 0; j < M; j++)
            if (!a[tot++]) putchar('x');
            else putchar(ans[i][j] ? 'o' : '_');
        printf("\n"); 
    }
    return 0; 
} 

猜你喜欢

转载自www.cnblogs.com/heyujun/p/10325124.html