luoguP4294 [WC2008]游览计划 斯坦纳树
这个其实就是状压DP+spfa.
本题需要输出方案,有一点点麻烦
code:
#include <bits/stdc++.h> #define ll long long #define N 12 #define inf 0x3f3f3f3f #define setIO(s) freopen(s".in","r",stdin) using namespace std; int dx[]={0,-1,0,1}; int dy[]={-1,0,1,0}; int n,m,K=0,tot; int val[N][N]; int bin[N],f[N*N][1<<N],id[N][N],X[N*N],Y[N*N],v[N*N],inq[N*N]; struct node { int pos,s; node(int pos=0,int s=0):pos(pos),s(s){} }pre[N*N][1<<N]; queue<int>q; void solve(int cur) { while(!q.empty()) { int u=q.front(); q.pop(),inq[u]=0; int x=X[u],y=Y[u]; for(int i=0;i<4;++i) { int xx=x+dx[i]; int yy=y+dy[i]; if(!(xx>=1&&xx<=n&&yy>=1&&yy<=m)) continue; int to=id[xx][yy]; if(f[to][cur]>f[u][cur]+v[to]) { f[to][cur]=f[u][cur]+v[to]; pre[to][cur]=node(u,cur); if(!inq[to]) { inq[to]=1; q.push(to); } } } } } int mk[N][N]; void dfs(int x,int now) { mk[X[x]][Y[x]]=1; if(!pre[x][now].pos) return; if(pre[x][now].pos==x) dfs(x,now^pre[x][now].s); dfs(pre[x][now].pos,pre[x][now].s); } int main() { // setIO("input"); int i,j,rr=0; scanf("%d%d",&n,&m); for(i=1;i<N;++i) bin[i]=1<<(i-1); for(i=1;i<=n;++i) for(j=1;j<=m;++j) id[i][j]=++tot,X[id[i][j]]=i,Y[id[i][j]]=j; memset(f,0x3f,sizeof(f)); for(i=1;i<=n;++i) for(j=1;j<=m;++j) { scanf("%d",&val[i][j]); v[id[i][j]]=val[i][j]; if(!val[i][j]) { ++K; rr=id[i][j]; f[id[i][j]][bin[K]]=0; } } for(i=1;i<bin[K+1];++i) { for(int pos=1;pos<=tot;++pos) { for(j=i&(i-1);j;j=i&(j-1)) { if(f[pos][j]+f[pos][i^j]-v[pos]<f[pos][i]) { f[pos][i]=f[pos][j]+f[pos][i^j]-v[pos]; pre[pos][i]=node(pos,j); } } if(f[pos][i]<inf) { inq[pos]=1; q.push(pos); } } solve(i); } printf("%d\n",f[rr][bin[K+1]-1]); dfs(rr,bin[K+1]-1); for(i=1;i<=n;++i) { for(j=1;j<=m;++j) { if(!val[i][j]) { printf("x"); } else { if(mk[i][j]) printf("o"); else printf("_"); } } printf("\n"); } return 0; }