zoukankan      html  css  js  c++  java
  • bzoj2595: [Wc2008]游览计划 斯坦纳树

    斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况
    我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有

    转移方程:

    dp[i][j]=min(dp[i][s]+dp[j-s]-a[i][j]) (表示有两个状态s和j-s都和i联通,我们把这两个状态联通起来,这样多算了一次a[i][j],减去即可)

    dp[i][j]=min(dp[i][j],dp[k][j]+a[i][k]) (如果i和k连着,那么,链接i和k,更新dp[i][j]),此处类似与最短路中的松弛操作

    来看这道题就是求平面上给定点的斯坦纳树,要求输出路径,我们更新状态的时候记录pre,
    spfa松弛(164 ms):

    /**************************************************************
        Problem: 2595
        User: walfy
        Language: C++
        Result: Accepted
        Time:164 ms
        Memory:7756 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define Max(a,  b) ((a)>(b)?(a):(b))
    #define Min(a,  b) ((a)<(b)?(a):(b))
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
     
    using namespace std;
     
    const double g=10.0,eps=1e-12;
    const int N=10+10,maxn=(1<<10)+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    struct Pre{
        int x,y,st;
    }pre[N][N][maxn];
    int f[N][N][maxn],n,m,a[N][N];
    queue<pii>q;
    bool vis[N][N];
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    void spfa(int st)
    {
        while(!q.empty())
        {
            pii p=q.front();q.pop();
            vis[p.fi][p.se]=0;
            for(int i=0;i<4;i++)
            {
                int nx=p.fi+dx[i],ny=p.se+dy[i];
                if(1<=nx&&nx<=n&&1<=ny&&ny<=m)
                {
                    if(f[p.fi][p.se][st]+a[nx][ny]<f[nx][ny][st])
                    {
                        f[nx][ny][st]=f[p.fi][p.se][st]+a[nx][ny];
                        pre[nx][ny][st]={p.fi,p.se,st};
                        if(!vis[nx][ny])
                        {
                            vis[nx][ny]=1;
                            q.push(mp(nx,ny));
                        }
                    }
                }
            }
        }
    }
    void dfs(int x,int y,int st)
    {
        vis[x][y]=1;
        Pre p=pre[x][y][st];
        if(!p.x)return ;
        dfs(p.x,p.y,p.st);
        if(x==p.x&&y==p.y)
            dfs(p.x,p.y,st-p.st);
    }
    int main()
    {
        int cnt=0,ansx=-1,ansy;
        scanf("%d%d",&n,&m);
        memset(f,inf,sizeof f);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
                if(!a[i][j])
                {
                    f[i][j][(1<<cnt)]=0;cnt++;
                    if(ansx==-1)ansx=i,ansy=j;
                }
            }
        }
        for(int st=0;st<(1<<cnt);st++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    for(int s=st;s;s=(s-1)&st)
                    {
                        if(f[i][j][s]+f[i][j][st-s]-a[i][j]<f[i][j][st])
                        {
                            f[i][j][st]=f[i][j][s]+f[i][j][st-s]-a[i][j];
                            pre[i][j][st]={i,j,s};
                        }
                    }
                    if(f[i][j][st]<inf)q.push(mp(i,j)),vis[i][j]=1;
                }
            }
            spfa(st);
        }
        printf("%d
    ",f[ansx][ansy][(1<<cnt)-1]);
        memset(vis,0,sizeof vis);
        dfs(ansx,ansy,(1<<cnt)-1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(!a[i][j])putchar('x');
                else putchar(vis[i][j]?'o':'_');
            }
            puts("");
        }
        return 0;
    }
    /***********************
     
    ***********************/
    

    dij松弛(432 ms):

    /**************************************************************
        Problem: 2595
        User: walfy
        Language: C++
        Result: Accepted
        Time:432 ms
        Memory:7756 kb
    ****************************************************************/
     
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define Max(a,  b) ((a)>(b)?(a):(b))
    #define Min(a,  b) ((a)<(b)?(a):(b))
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
     
    using namespace std;
     
    const double g=10.0,eps=1e-12;
    const int N=10+10,maxn=(1<<10)+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
     
    struct Pre{
        int x,y,st;
    }pre[N][N][maxn];
    int f[N][N][maxn],n,m,a[N][N];
    bool vis[N][N];
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    int state;
    struct node{
        int x,y;
        bool operator <(const node&rhs)const{
            return f[x][y][state]<f[rhs.x][rhs.y][state];
        }
    };
    priority_queue<node>q;
    void dij(int st)
    {
        while(!q.empty())
        {
            node p=q.top();q.pop();
            for(int i=0;i<4;i++)
            {
                int nx=p.x+dx[i],ny=p.y+dy[i];
                if(1<=nx&&nx<=n&&1<=ny&&ny<=m)
                {
                    if(f[p.x][p.y][st]+a[nx][ny]<f[nx][ny][st])
                    {
                        f[nx][ny][st]=f[p.x][p.y][st]+a[nx][ny];
                        pre[nx][ny][st]={p.x,p.y,st};
                        q.push({nx,ny});
                    }
                }
            }
        }
    }
    void dfs(int x,int y,int st)
    {
        vis[x][y]=1;
        Pre p=pre[x][y][st];
        if(!p.x)return ;
        dfs(p.x,p.y,p.st);
        if(x==p.x&&y==p.y)
            dfs(p.x,p.y,st-p.st);
    }
    int main()
    {
     
        int cnt=0,ansx=-1,ansy;
        scanf("%d%d",&n,&m);
        memset(f,inf,sizeof f);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
                if(!a[i][j])
                {
                    f[i][j][(1<<cnt)]=0;cnt++;
                    if(ansx==-1)ansx=i,ansy=j;
                }
            }
        }
        for(int st=0;st<(1<<cnt);st++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    for(int s=st;s;s=(s-1)&st)
                    {
                        if(f[i][j][s]+f[i][j][st-s]-a[i][j]<f[i][j][st])
                        {
                            f[i][j][st]=f[i][j][s]+f[i][j][st-s]-a[i][j];
                            pre[i][j][st]={i,j,s};
                        }
                    }
                    if(f[i][j][st]<inf)q.push({i,j});
                }
            }
            state=st;
            dij(st);
        }
        printf("%d
    ",f[ansx][ansy][(1<<cnt)-1]);
        memset(vis,0,sizeof vis);
        dfs(ansx,ansy,(1<<cnt)-1);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(!a[i][j])putchar('x');
                else putchar(vis[i][j]?'o':'_');
            }
            puts("");
        }
        return 0;
    }
    /***********************
     
    ***********************/
    
  • 相关阅读:
    【GoLang】转载:我为什么放弃Go语言,哈哈
    【GoLang】golang runtime 调度原理
    【GoLang】golang 微服务框架 介绍
    Redis缓存与springboot集成
    Redis分布式锁
    springboot配置文件的配置
    分布式事务之学习
    快速学习
    CAP定理为什么只能同时满足两个
    requestMapping之地址映射
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9345822.html
Copyright © 2011-2022 走看看