[bzoj 4774]修路

Posted papercloud

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj 4774]修路相关的知识,希望对你有一定的参考价值。

传送门

Description?

该题出现在了D4T1

可以把最后的图分成若干个不相交的部分,显然每个部分都是包含的指定点集合的一个斯坦纳树

枚举子集合并即可


Code?

/*
    斯坦纳树;O(n*3^n+kE*2^n) 暂且把O(k*E)当成是spfa的复杂度
    15:15~16:20
*/
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const int MN=10005,MM=20005,inf=0x3f3f3f3f;
int n,m,k;
struct edge{int to,w,nex;}e[MM<<1];int hr[MN],en;
inline void ins(int f,int t,int w)
{
    e[++en]=(edge){t,w,hr[f]};hr[f]=en;
    e[++en]=(edge){f,w,hr[t]};hr[t]=en;
}
std::queue<int> q;
int f[1<<10][MN],g[1<<10],refer[1<<5],ans=inf;
bool inq[MN];
void spfa(int *d)
{
    register int u,i;
    while(!q.empty())
    {
        u=q.front();q.pop();inq[u]=false;
        for(i=hr[u];i;i=e[i].nex)
            if(d[e[i].to]>d[u]+e[i].w)
            {
                d[e[i].to]=d[u]+e[i].w;
                if(!inq[e[i].to]) q.push(e[i].to),inq[e[i].to]=true;
            }
    }
}
int get(int x)
{
    if(x<=k/2) return x*2-1;
    if(x+k/2>n) return (n-x+1)*2;
    return x+k/2;
}
int main()
{
    register int i,j,x,y,S,SS,SSS,s;
    n=read();m=read();k=read()<<1;SS=1<<k;SSS=1<<(k>>1);
    while(m--)x=get(read()),y=get(read()),ins(x,y,read());
    memset(f,0x3f,sizeof f);
    for(i=1;i<=k;++i) f[1<<i-1][i]=0;
    for(S=1;S<SS;++S)
    {
        for(i=1;i<=n;++i)
        {
            for(s=S&(S-1);s;s=(s-1)&S) f[S][i]=min(f[S][i],f[s][i]+f[S^s][i]);
            if(f[S][i]<inf) q.push(i);
        }
        spfa(f[S]);g[S]=inf;
        for(i=1;i<=n;++i) g[S]=min(g[S],f[S][i]);
    }
    for(i=0;i<SSS;++i)
    {
        s=0;
        for(j=0;j<k/2;++j) if(i>>j&1) s|=1<<(j*2);
        refer[i]=s|(s<<1);
    }
    for(S=1;S<SSS;++S)for(s=S&(S-1);s;s=(s-1)&S)
        g[refer[S]]=min(g[refer[S]],g[refer[s]]+g[refer[S^s]]);
    printf("%d
",g[SS-1]==inf?-1:g[SS-1]);
    return 0;
}



Blog来自PaperCloud,未经允许,请勿转载,TKS!

以上是关于[bzoj 4774]修路的主要内容,如果未能解决你的问题,请参考以下文章

A - 修路

[USACO08FEB]修路Making the Grade

算法普里姆算法 Prim算法解决修路问题

nyoj 118 修路方案

[USACO08FEB]修路题解

修路方案(次小生成树)