斯坦纳树的问题模型是:有一个图,要求保留图中最少的边/最小的边权和使得某k个点相互连通。最小生成树是斯坦纳树的一种特殊情况。

我们用f[i]][j][s]表示方格中i,j位置与各个景点之间的联通情况。
如果景点数为3时,111表示全部联通, 101表示第二个景点没有联通。。。
当然第x个景点的 f[i][j][(1<<x)] = 0,其他的情况先初始化为inf。

状态怎么转移?
有两种情况
1.某个状态的子状态(11011->10001)。
2.相邻的位置转移过来的。

子状态的话需要知道一个枚举子状态的技巧:

for(int s = st&(st-1); s; s = st&(s-1))

相邻的状态转移就要用spfa了。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1<<12;
int Case = 1;
int n, m, cc[12][12], f[12][12][maxn], vis[12][12], res[12][12];
int dr[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
queue<pair<int, int> >Q;
struct node{
	int i, j, s;
}pre[12][12][maxn];

void dfs(int x, int y, int s) {
	if(!pre[x][y][s].s) return;
	res[x][y] = 1;
	dfs(pre[x][y][s].i, pre[x][y][s].j, pre[x][y][s].s);
	if(pre[x][y][s].i == x && pre[x][y][s].j == y)
		dfs(x, y, pre[x][y][s].s^s);
}

void spfa(int s) {
	while(!Q.empty()) {
		int x = Q.front().first, y = Q.front().second;Q.pop();
		vis[x][y] = 0;
		for(int i = 0; i < 4; i++) {
			int nx = x + dr[i][0];
			int ny = y + dr[i][1];
			if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && f[x][y][s] + cc[nx][ny] < f[nx][ny][s]) {
				f[nx][ny][s] = f[x][y][s] + cc[nx][ny];
				pre[nx][ny][s] = node{x, y, s};
				if(!vis[nx][ny]) Q.push(make_pair(nx, ny)), vis[nx][ny] = 1;
			}
		}
	}
}

void solve() {
	int sx, sy;
    scanf("%d%d", &n, &m);
   	memset(f, 0x3f3f, sizeof(f));
    int num = 0;
    for(int i = 1; i <= n; i++) {
    	for(int j = 1; j <= m; j++) {
    		scanf("%d", &cc[i][j]);
    		if(!cc[i][j]) {f[i][j][(1<<(num++))] = 0;sx = i;sy = j;}
    	}
    }
    int mx = 1<<num;
    for(int st = 0; st < mx; st++) {
    	for(int i = 1; i <= n; i++) {
    		for(int j = 1; j <= m; j++) {
    			for(int s = st&(st-1); s; s = st&(s-1)) {
    				if(f[i][j][s] + f[i][j][st-s] - cc[i][j] < f[i][j][st]) {
    					f[i][j][st] = f[i][j][s] + f[i][j][st-s] - cc[i][j];
    					pre[i][j][st] = node{i, j, s};
    				}
    			}
    			if(f[i][j][st] < 0x3f3f) Q.push(make_pair(i, j)), vis[i][j] = 1;
    		}
    	}
    	spfa(st);
    }
   	printf("%d\n", f[sx][sy][(1<<num)-1]);
   	dfs(sx, sy, (1<<num)-1);
   	for(int i = 1; i <= n; i++) {
   		for(int j = 1; j <= m; j++) {
   			if(cc[i][j] == 0) printf("x");
   			else if(res[i][j]) printf("o");
   			else printf("_");
   		}
   		printf("\n");
   	}
    return;
}

int main() {
    while(Case--) {
        solve();
    }
    return 0;
}