【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; 
} 
posted @ 2019-01-26 22:19  heyujun  阅读(253)  评论(0编辑  收藏  举报