[最小斯坦纳树] Baltic OI 2016. Cities

应该最小斯坦纳树裸题吧…

加个spfa的那个优化就可以了

#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N=100010;

int n,k,m,cnt,G[N];
struct iedge{
    int t,nx,w;
}E[N<<2];

inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
    char c=nc(); x=0;
    for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

ll f[40][N],inf;
int vis[N];
int imp[10];

deque<int> Q;

inline void spfa(ll *f){
    for(int i=1;i<=n;i++){
        vis[i]=0;
        if(f[i]!=inf) Q.push_back(i);
    }
    while(!Q.empty()){
        int x=Q.front(); Q.pop_front(); vis[x]=0;
        for(int i=G[x];i;i=E[i].nx)
            if(f[E[i].t]>f[x]+E[i].w){
                f[E[i].t]=f[x]+E[i].w;
                if(!vis[E[i].t]){
                    vis[E[i].t]=1;
                    (Q.empty() || f[E[i].t]<=f[Q.front()])?Q.push_front(E[i].t):Q.push_back(E[i].t);
                }
            }
    }
}

inline void addedge(int x,int y,int z){
    E[++cnt].t=y; E[cnt].nx=G[x]; E[cnt].w=z; G[x]=cnt;
    E[++cnt].t=x; E[cnt].nx=G[y]; E[cnt].w=z; G[y]=cnt;
}

int main(){
    freopen("cities.in","r",stdin);
    freopen("cities.out","w",stdout);
    rea(n); rea(k); rea(m);
    memset(f,0x7f>>1,sizeof(f)); inf=**f;
    for(int i=0;i1<0;
    }
    for(int i=1,x,y,z;i<=m;i++){
        rea(x); rea(y); rea(z);
        addedge(x,y,z);
    }
    for(int S=1;S<(1<for(int i=1;i<=n;i++)
            for(int ss=(S-1)&S;ss;ss=(ss-1)&S)
                g[i]=min(g[i],f[ss][i]+f[S^ss][i]);
        spfa(g);
    }
    ll ans=inf;
    for(int i=1;i<=n;i++) ans=min(ans,f[(1<1][i]);
    cout<return 0;
}

你可能感兴趣的:(DP,状压DP,最小-最大生成树)