• P4294 [WC2008]游览计划 (斯坦纳树)


    题目链接

    差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复。

    题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=10+2,inf=0x3f3f3f3f;
     5 const int dx[]= {0,0,-1,1};
     6 const int dy[]= {-1,1,0,0};
     7 int n,m,k,dp[1<<10][N][N],a[N][N],inq[N][N];
     8 char s[N][N];
     9 struct D {int x,y;} X[N];
    10 struct Ans {int S,x,y;} ansS,nxt[1<<10][N][N];
    11 queue<D> q;
    12 void upd(int x,int y,int c,int S,int x2,int y2) {
    13     if(dp[S][x][y]>c) {
    14         dp[S][x][y]=c;
    15         nxt[S][x][y]= {S,x2,y2};
    16         if(!inq[x][y])inq[x][y]=1,q.push({x,y});
    17     }
    18 }
    19 void spfa(int S) {
    20     while(q.size())q.pop();
    21     memset(inq,0,sizeof inq);
    22     for(int i=1; i<=n; ++i)
    23         for(int j=1; j<=m; ++j)
    24             if(dp[S][i][j]!=inf)inq[i][j]=1,q.push({i,j});
    25     while(q.size()) {
    26         int x=q.front().x,y=q.front().y;
    27         q.pop(),inq[x][y]=0;
    28         for(int i=0; i<4; ++i) {
    29             int x2=x+dx[i],y2=y+dy[i];
    30             if(x2<1||x2>n||y2<1||y2>m)continue;
    31             upd(x2,y2,dp[S][x][y]+a[x2][y2],S,x,y);
    32         }
    33     }
    34 }
    35 void dfs(int S,int x,int y) {
    36     if(!a[x][y])s[x][y]='x';
    37     else s[x][y]='o';
    38     int S2=nxt[S][x][y].S,x2=nxt[S][x][y].x,y2=nxt[S][x][y].y;
    39     if(!S2)return;
    40     else if(S2==S)dfs(S2,x2,y2);
    41     else dfs(S2,x2,y2),dfs(S^S2,x2,y2);
    42 }
    43 int main() {
    44     scanf("%d%d",&n,&m);
    45     for(int i=1; i<=n; ++i)
    46         for(int j=1; j<=m; ++j) {
    47             scanf("%d",&a[i][j]);
    48             if(!a[i][j])X[k++]= {i,j};
    49         }
    50     memset(dp,inf,sizeof dp);
    51     for(int i=0; i<k; ++i)dp[1<<i][X[i].x][X[i].y]=a[X[i].x][X[i].y];
    52     for(int S=1; S<(1<<k); ++S) {
    53         for(int S2=(S-1)&S; S2; S2=(S2-1)&S)
    54             for(int i=1; i<=n; ++i)
    55                 for(int j=1; j<=m; ++j) {
    56                     dp[S][i][j]=min(dp[S][i][j],dp[S2][i][j]+dp[S^S2][i][j]-a[i][j]);
    57                     if(dp[S][i][j]==dp[S2][i][j]+dp[S^S2][i][j]-a[i][j])nxt[S][i][j]= {S2,i,j};
    58                 }
    59         spfa(S);
    60     }
    61     int ans=inf;
    62     for(int i=1; i<=n; ++i)
    63         for(int j=1; j<=m; ++j) {
    64             ans=min(ans,dp[(1<<k)-1][i][j]);
    65             if(ans==dp[(1<<k)-1][i][j])ansS= {(1<<k)-1,i,j};
    66         }
    67     for(int i=1; i<=n; ++i)
    68         for(int j=1; j<=m; ++j)s[i][j]='_';
    69     dfs(ansS.S,ansS.x,ansS.y);
    70     printf("%d
    ",ans);
    71     for(int i=1; i<=n; ++i) {
    72         for(int j=1; j<=m; ++j)putchar(s[i][j]);
    73         puts("");
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    BZOJ4004: [JLOI2015]装备购买
    POJ3696:The Luckiest number
    BZOJ1053: [HAOI2007]反素数ant
    BZOJ1029: [JSOI2007]建筑抢修
    牛站(贪心+暴力做法)
    浅谈SPFA(没有特别的探讨,只是对某天晚上的思考做个记录)
    火车进栈问题(如何快速计算单个组合数)
    雷达设备
    畜栏预定
    防晒
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11630510.html
Copyright © 2020-2023  润新知