斯坦纳生成树

dp版
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100;
const int M=2000+10;
const int INF=1e8;

int dp[N][1<<10],s[N];
int dis[N][N];

int n,m,k;
void floyd(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
}
void _stn(int ed){
    floyd();
    for(int y=0;y<ed;y++){
        for(int x=1;x<=n;x++)dp[x][y]=INF;
    }
    for(int i=1;i<=n;i++){
        if(i<=k)s[i]=1<<(i-1),dp[i][s[i]]=0;
        else if(i>=n-k+1)s[i]=1<<(n-i+k),dp[i][s[i]]=0;
        else s[i]=0;
    }
    for(int y=0;y<ed;y++){
        for(int x=1;x<=n;x++){
            for(int i=(y-1)&y;i;i=(i-1)&y){
                dp[x][y]=min(dp[x][y],dp[x][i|s[x]]+dp[x][(y-i)|s[x]]);
            }
        }
        for(int x=1;x<=n;x++){
            for(int x1=1;x1<=n;x1++){
                dp[x1][y|s[x1]]=min(dp[x1][y|s[x1]],dp[x][y]+dis[x][x1]);
            }
        }
    }
}

spfa版

//hdu 4085

int vis[N][1<<10];
int dp[N][1<<10],s[N];
queue<int> qq;
int update(int x,int y,int w){
    if(dp[x][y]>w){
        dp[x][y]=w;return 1;
    }
    return 0;
}
void spfa(){
    while(!qq.empty()){
        int x=qq.front()/10000,y=qq.front()%10000;
        vis[x][y]=0;
        qq.pop();
        for(int i=head[x];i!=-1;i=e[i].next){
            int v=e[i].v,w=e[i].w;
            if(update(v,y|s[v],dp[x][y]+w)&&y==(y|s[v])&&!vis[v][y]){
                vis[v][y]=1,qq.push(v*10000+y);
            }
        }
    }
}
int n,m,k;
void _stn(int ed){
    for(int y=0;y<ed;y++){
        for(int x=1;x<=n;x++)dp[x][y]=INF;
    }
    for(int i=1;i<=n;i++){
        if(i<=k)s[i]=1<<(i-1),dp[i][s[i]]=0;
        else if(i>=n-k+1)s[i]=1<<(n-i+k),dp[i][s[i]]=0;
        else s[i]=0;
    }
    memset(vis,0,sizeof(vis));
    for(int y=0;y<ed;y++){
        for(int x=1;x<=n;x++){
            for(int i=(y-1)&y;i;i=(i-1)&y){
                dp[x][y]=min(dp[x][y],dp[x][i|s[x]]+dp[x][(y-i)|s[x]]);
            }
            if(dp[x][y]<INF){
                qq.push(x*10000+y);vis[x][y]=1;
            }
        }
        spfa();
    }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值