BZOJ 2595: [Wc2008]游览计划
斯坦纳树
Dijkstra+堆貌似慢了一倍
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,m,lim=1,F[12][12][1050],a[12][12],vis[12][12],instack[12][12]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; struct node{ int x,y,sta; }Pre[12][12][1050],q[1000005]; void spfa(int now){ // printf("ans:%d\n",now); int head=0,tail=1; memset(instack,0,sizeof(instack)); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++){ q[++tail]=(node){i,j,0}; instack[i][j]=1; } while (head<tail){ head++; int x=q[head].x,y=q[head].y; instack[x][y]=0; for (int i=0; i<4; i++){ int fx=x+dx[i],fy=y+dy[i]; if (fx<1 || fx>n || fy<1 || fy>m) continue; if (F[fx][fy][now]>F[x][y][now]+a[fx][fy]){ F[fx][fy][now]=F[x][y][now]+a[fx][fy]; Pre[fx][fy][now]=(node){x,y,now}; if (!instack[fx][fy]){ instack[fx][fy]=1; q[++tail]=(node){fx,fy,0}; } } } } } void solve(int x,int y,int now){ if (!now) return; int X=Pre[x][y][now].x,Y=Pre[x][y][now].y,sta=Pre[x][y][now].sta; solve(X,Y,sta); if (X==x && Y==y){ if (sta) solve(X,Y,now-sta); } else vis[x][y]=1; } int main(){ scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++){ scanf("%d",&a[i][j]); if (a[i][j]==0) lim<<=1; } for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) for (int now=1; now<lim; now++) F[i][j][now]=1e9; int num=0; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (!a[i][j]) { F[i][j][1<<num]=0; num++; } for (int now=1; now<lim; now++){ for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) for (int sta=now; sta; sta=((sta-1)&now)){ if (F[i][j][now]>F[i][j][sta]+F[i][j][now-sta]-a[i][j]){ F[i][j][now]=F[i][j][sta]+F[i][j][now-sta]-a[i][j]; Pre[i][j][now]=(node){i,j,sta}; } } spfa(now); } int ansx=0,ansy=0; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) if (!a[i][j]){ ansx=i,ansy=j; break; } solve(ansx,ansy,lim-1); printf("%d\n",F[ansx][ansy][lim-1]); for (int i=1; i<=n; i++){ for (int j=1; j<=m; j++) if (!a[i][j]) printf("x"); else if (vis[i][j]) printf("o"); else printf("_"); printf("\n"); } return 0; }